diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 84a03c743b95a..2e4e0447ede95 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -4,5 +4,7 @@ f4118e110a46de3ffb799e7d79bf15128d1646ea ae0a783425b80b78376488619bf9106e69193fa4 9c1e36257c4df0929179462d6b2bdd00453ac8aa 6ae74d38e3d20d0ffcc66c7c3d28767fab76bdfb -# Prefix all sprintf() calls 6ce530c5e90397d88e3a76a56db266c74d651584 +77bd236b8da064c90b19b84a35becfb3e43348db +d0bc10e7432901098fe50bcccad53f487978c33d +2e0c0d39bdc99712cc40b8a5b77e267150a92509 diff --git a/.gitattributes b/.gitattributes index c7aefa05ef8be..a619132d3516d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,7 +7,7 @@ /src/Symfony/Component/Translation/Bridge export-ignore /src/Symfony/Component/Emoji/Resources/data/* linguist-generated=true /src/Symfony/Component/Intl/Resources/data/*/* linguist-generated=true -/src/Symfony/Component/JsonEncoder/Tests/Fixtures/encoder/* linguist-generated=true -/src/Symfony/Component/JsonEncoder/Tests/Fixtures/decoder/* linguist-generated=true +/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/* linguist-generated=true +/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_reader/* linguist-generated=true /src/Symfony/**/.github/workflows/close-pull-request.yml linguist-generated=true /src/Symfony/**/.github/PULL_REQUEST_TEMPLATE.md linguist-generated=true diff --git a/.github/expected-missing-return-types.diff b/.github/expected-missing-return-types.diff index 9faed9a44dd73..679740ed3a33c 100644 --- a/.github/expected-missing-return-types.diff +++ b/.github/expected-missing-return-types.diff @@ -48,7 +48,7 @@ diff --git a/src/Symfony/Component/BrowserKit/AbstractBrowser.php b/src/Symfony/ diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php -@@ -94,5 +94,5 @@ abstract class NodeDefinition implements NodeParentInterface +@@ -115,5 +115,5 @@ abstract class NodeDefinition implements NodeParentInterface * @return NodeParentInterface|NodeBuilder|self|ArrayNodeDefinition|VariableNodeDefinition */ - public function end(): NodeParentInterface @@ -58,21 +58,21 @@ diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php -@@ -163,5 +163,5 @@ class Command +@@ -201,5 +201,5 @@ class Command implements SignalableCommandInterface * @return void */ - protected function configure() + protected function configure(): void { } -@@ -195,5 +195,5 @@ class Command +@@ -233,5 +233,5 @@ class Command implements SignalableCommandInterface * @return void */ - protected function interact(InputInterface $input, OutputInterface $output) + protected function interact(InputInterface $input, OutputInterface $output): void { } -@@ -211,5 +211,5 @@ class Command +@@ -249,5 +249,5 @@ class Command implements SignalableCommandInterface * @return void */ - protected function initialize(InputInterface $input, OutputInterface $output) @@ -474,14 +474,14 @@ diff --git a/src/Symfony/Component/HttpKernel/KernelInterface.php b/src/Symfony/ diff --git a/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php b/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php --- a/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AttributeClassLoader.php -@@ -253,5 +253,5 @@ abstract class AttributeClassLoader implements LoaderInterface +@@ -277,5 +277,5 @@ abstract class AttributeClassLoader implements LoaderInterface * @return string */ - protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) + protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method): string { $name = str_replace('\\', '_', $class->name).'_'.$method->name; -@@ -355,5 +355,5 @@ abstract class AttributeClassLoader implements LoaderInterface +@@ -379,5 +379,5 @@ abstract class AttributeClassLoader implements LoaderInterface * @return void */ - abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, object $attr); @@ -578,7 +578,7 @@ diff --git a/src/Symfony/Component/Translation/Extractor/ExtractorInterface.php diff --git a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php --- a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php +++ b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithPhpDoc.php -@@ -15,5 +15,5 @@ final class DummyWithPhpDoc +@@ -50,5 +50,5 @@ final class DummyWithPhpDoc * @return Dummy */ - public function getNextDummy(mixed $dummy): mixed diff --git a/.github/patch-types.php b/.github/patch-types.php index fc6be71995397..9e4f12c6dfa76 100644 --- a/.github/patch-types.php +++ b/.github/patch-types.php @@ -53,8 +53,11 @@ case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/'): case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php81Dummy.php'): case false !== strpos($file, '/src/Symfony/Component/Runtime/Internal/ComposerPlugin.php'): + case false !== strpos($file, '/src/Symfony/Component/Security/Http/Tests/Fixtures/IsGrantedAttributeMethodsWithClosureController.php'): + case false !== strpos($file, '/src/Symfony/Component/Security/Http/Tests/Fixtures/IsGrantedAttributeWithClosureController.php'): case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Fixtures/'): case false !== strpos($file, '/src/Symfony/Component/Serializer/Tests/Normalizer/Features/ObjectOuter.php'): + case false !== strpos($file, '/src/Symfony/Component/Validator/Tests/Constraints/Fixtures/WhenTestWithClosure.php'): case false !== strpos($file, '/src/Symfony/Component/Validator/Tests/Fixtures/NestedAttribute/Entity.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/NotLoadableClass.php'): case false !== strpos($file, '/src/Symfony/Component/VarDumper/Tests/Fixtures/ReflectionIntersectionTypeFixture.php'): diff --git a/.github/workflows/fabbot.yml b/.github/workflows/fabbot.yml new file mode 100644 index 0000000000000..a187b49ee6991 --- /dev/null +++ b/.github/workflows/fabbot.yml @@ -0,0 +1,15 @@ +name: CS + +on: + pull_request: + +permissions: + contents: read + +jobs: + call-fabbot: + name: Fabbot + uses: symfony-tools/fabbot/.github/workflows/fabbot.yml@main + with: + package: Symfony + check_license: true diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 6eff30a0a6e35..ca6b82974d22d 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -34,6 +34,8 @@ jobs: - php: '8.3' - php: '8.4' - php: '8.5' + # to be removed when ext-zstd is ready for PHP 8.5 + extensions: amqp,apcu,brotli,igbinary,intl,mbstring,memcached,redis,relay #mode: experimental fail-fast: false @@ -233,7 +235,7 @@ jobs: - name: Run AssetMapper without ext-brotli nor ext-zstd if: "! matrix.mode" run: | - sudo rm /etc/php/*/cli/conf.d/*-{brotli,zstd}.ini + sudo rm -f /etc/php/*/cli/conf.d/*-{brotli,zstd}.ini ./phpunit src/Symfony/Component/AssetMapper - name: Run tests with SIGCHLD enabled PHP diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 62ab3e5e6a3aa..e0a663386beee 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -43,13 +43,15 @@ jobs: run: | $env:Path = 'c:\php;' + $env:Path mkdir c:\php && cd c:\php - iwr -outf php-8.2.0-Win32-vs16-x86.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.2.0-Win32-vs16-x86.zip - 7z x php-8.2.0-Win32-vs16-x86.zip -y >nul + iwr -outf php.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php-8.2.0-Win32-vs16-x86.zip + 7z x php.zip -y >nul cd ext - iwr -outf php_apcu-5.1.22-8.2-ts-vs16-x86.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.22-8.2-ts-vs16-x86.zip - 7z x php_apcu-5.1.22-8.2-ts-vs16-x86.zip -y >nul - iwr -outf php_redis-6.0.0-dev-8.2-ts-vs16-x86.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-6.0.0-dev-8.2-ts-vs16-x86.zip - 7z x php_redis-6.0.0-dev-8.2-ts-vs16-x86.zip -y >nul + iwr -outf php_apcu.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.22-8.2-ts-vs16-x86.zip + 7z x php_apcu.zip -y >nul + iwr -outf php_igbinary.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_igbinary-3.2.16-8.2-ts-vs16-x86.zip + 7z x php_igbinary.zip -y >nul + iwr -outf php_redis.zip https://github.com/symfony/binary-utils/releases/download/v0.1/php_redis-6.0.0-dev-8.2-ts-vs16-x86.zip + 7z x php_redis.zip -y >nul cd .. Copy php.ini-development php.ini-min "memory_limit=-1" >> php.ini-min diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index f3e25eaa66a0d..d31af1aab2e20 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -35,6 +35,7 @@ '@PHPUnit75Migration:risky' => true, '@Symfony' => true, '@Symfony:risky' => true, + 'phpdoc_var_annotation_correct_order' => true, 'protected_to_private' => false, 'header_comment' => [ 'header' => implode('', $fileHeaderParts), @@ -44,7 +45,7 @@ '(?P.*)??', preg_quote($fileHeaderParts[1], '/'), '/s', - ]) + ]), ], ]) ->setRiskyAllowed(true) diff --git a/CHANGELOG-7.2.md b/CHANGELOG-7.2.md index d6d188669de42..d128815948827 100644 --- a/CHANGELOG-7.2.md +++ b/CHANGELOG-7.2.md @@ -7,6 +7,55 @@ in 7.2 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v7.2.0...v7.2.1 +* 7.2.8 (2025-06-28) + + * bug #60044 [Console] Table counts wrong column width when using colspan and `setColumnMaxWidth()` (vladimir-vv) + * bug #60042 [Console] Table counts wrong number of padding symbols in `renderCell()` method when cell contain unicode variant selector (vladimir-vv) + * bug #60594 [Cache] Fix using a `ChainAdapter` as an adapter for a pool (IndraGunawan) + * bug #60483 [HttpKernel] Fix `#[MapUploadedFile]` handling for optional file uploads (santysisi) + * bug #60413 [Serializer] Fix collect_denormalization_errors flag in defaultContext (dmbrson) + * bug #60820 [TypeInfo] Fix handling `ConstFetchNode` (norkunas) + * bug #60908 [Uid] Improve entropy of the increment for UUIDv7 (nicolas-grekas) + * bug #60914 [Console] Fix command option mode (InputOption::VALUE_REQUIRED) (gharlan) + * bug #60919 [VarDumper] Avoid deprecated call in PgSqlCaster (vrana) + * bug #60909 [TypeInfo] use an EOL-agnostic approach to parse class uses (xabbuh) + * bug #60888 [Intl] Fix locale validator when canonicalize is true (rdavaillaud) + * bug #60885 [Notifier] Update fake SMS transports to use contracts event dispatcher (paulferrett) + * bug #60859 [TwigBundle] fix preload unlinked class `BinaryOperatorExpressionParser` (Grummfy) + * bug #60772 [Mailer] [Transport] Send clone of `RawMessage` instance in `RoundRobinTransport` (jnoordsij) + * bug #60842 [DependencyInjection] Fix generating adapters of functional interfaces (nicolas-grekas) + * bug #60809 [Serializer] Fix `TraceableSerializer` when called from a callable inside `array_map` (OrestisZag) + * bug #60511 [Serializer] Add support for discriminator map in property normalizer (ruudk) + * bug #60780 [FrameworkBundle] Fix argument not provided to `add_bus_name_stamp_middleware` (maxbaldanza) + * bug #60826 [DependencyInjection] Fix inlining when public services are involved (nicolas-grekas) + * bug #60806 [HttpClient] Limit curl's connection cache size (nicolas-grekas) + * bug #60705 [FrameworkBundle] Fix allow `loose` as an email validation mode (rhel-eo) + * bug #60759 [Messenger] Fix float value for worker memory limit (ro0NL) + * bug #60785 [Security] Handle non-callable implementations of `FirewallListenerInterface` (MatTheCat) + * bug #60781 [DomCrawler] Allow selecting `button`s by their `value` (MatTheCat) + * bug #60775 [Validator] flip excluded properties with keys with Doctrine-style constraint config (xabbuh) + * bug #60774 [FrameworkBundle] Fixes getting a type error when the secret you are trying to reveal could not be decrypted (jack-worman) + * bug #60779 Silence E_DEPRECATED and E_USER_DEPRECATED (nicolas-grekas) + * bug #60502 [HttpCache] Hit the backend only once after waiting for the cache lock (mpdude) + * bug #60771 [Runtime] fix compatibility with Symfony 7.4 (xabbuh) + * bug #59910 [Form] Keep submitted values when `keep_as_list` option of collection type is enabled (kells) + * bug #60638 [Form] Fix `keep_as_list` when data is not an array (MatTheCat) + * bug #60691 [DependencyInjection] Fix `ServiceLocatorTagPass` indexes handling (MatTheCat) + * bug #60676 [Form] Fix handling the empty string in NumberToLocalizedStringTransformer (gnat42) + * bug #60694 [Intl] Add missing currency (NOK) localization (en_NO) (llupa) + * bug #60711 [Intl] Ensure data consistency between alpha and numeric codes (llupa) + * bug #60724 [VarDumper] Fix dumping LazyObjectState when using VarExporter v8 (nicolas-grekas) + * bug #60693 [FrameworkBundle] ensureKernelShutdown in tearDownAfterClass (cquintana92) + * bug #60564 [FrameworkBundle] ensureKernelShutdown in tearDownAfterClass (cquintana92) + * bug #60645 [PhpUnitBridge] Skip bootstrap for PHPUnit >=10 (HypeMC) + * bug #60655 [TypeInfo] Handle `key-of` and `value-of` types (mtarld) + * bug #60640 [Mailer] use STARTTLS for SMTP with MailerSend (xabbuh) + * bug #60648 [Yaml] fix support for years outside of the 32b range on x86 arch on PHP 8.4 (nicolas-grekas) + * bug #60616 skip interactive questions asked by Composer (xabbuh) + * bug #60584 [DependencyInjection] Make `YamlDumper` quote resolved env vars if necessary (MatTheCat) + * bug #60588 [Notifier][Clicksend] Fix lack of recipient in case DSN does not have optional LIST_ID param (alifanau) + * bug #60547 [HttpFoundation] Fixed 'Via' header regex (thecaliskan) + * 7.2.7 (2025-05-29) * bug #60549 [Translation] Add intl-icu fallback for MessageCatalogue metadata (pontus-mp) diff --git a/CHANGELOG-7.3.md b/CHANGELOG-7.3.md index da566f84844cb..af46cc6a27d3a 100644 --- a/CHANGELOG-7.3.md +++ b/CHANGELOG-7.3.md @@ -7,6 +7,64 @@ in 7.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v7.3.0...v7.3.1 +* 7.3.2 (2025-07-31) + + * bug #61276 [DependencyInjection] Escape parameters before resolving env placeholders (MatTheCat) + * bug #61268 [Console] [Table] Fix unnecessary wrapping (schlndh) + * bug #61085 [Lock] Fix using fractional TTLs (manuelderuiter) + * bug #61271 [Messenger] disable detecting modified indexes with DBAL 4.3 (xabbuh) + * bug #61242 [Console] [Table] Fix invalid UTF-8 due to text wrapping (schlndh) + * bug #61234 [Cache] RedisTrait::doFetch should use pipeline with GET's instead of MGET for Relay\Cluster (dorrogeray) + * bug #61246 [VarDumper] Use unique identifier for `RequestContextProvider` (ToshY) + * bug #61261 [FrameworkBundle] Fix `lint:container --resolve-env-vars` (MatTheCat) + * bug #61080 [Console] Fix `TreeHelper::addChild` when providing a string (jtattevin) + * bug #60296 [Serializer] Handle invalid mapping type property type (KorvinSzanto) + * bug #58995 [Config] Do not generate unreachable configuration paths (bobvandevijver) + * bug #60867 [WebProfilerBundle] Fix missing indent on non php files opended in the profiler (phcorp) + * bug #61233 [ObjectMapper] skip reading uninitialized values (soyuka) + * bug #61199 [JsonPath] Fix parsing invalid Unicode codepoints (nicolas-grekas) + * bug #61223 [Mailer][Brevo] Update Webhook IPs (jarbey) + * bug #61201 [Console] Fix JSON description for negatable input flags (nicolas-grekas) + * bug #61220 [Cache] fix compatibility with different Relay versions (xabbuh) + * bug #61194 [Security] Fix added $token argument to UserCheckerInterface::checkPostAuth() (nicolas-grekas) + * bug #61146 [ObjectMapper] initialize lazy objects (soyuka) + * bug #61161 [Lock] Fallback to `eval` when `LOAD` fails due to missing script (santysisi) + * bug #61151 [ObjectMapper] update promoted properties w/ an object as target (soyuka) + * bug #61158 [FrameworkBundle] Add missing html5-allow-no-tld to XSD file (nicolas-grekas) + * bug #61144 [VarDumper] Fix dumping on systems that don't have a working iconv (nicolas-grekas) + * bug #60798 [JsonPath] Handle slice selector overflow (alexandre-daubois) + * bug #61138 [Console] fix profiler with overridden `run()` method (vinceAmstoutz) + * bug #61079 [Config] Fix support for attributes on class constants and enum cases (ruudk) + * bug #61131 [Validator] error if the fields option is missing for the Collection constraint (xabbuh) + * bug #61111 [Translation] fix support of `TranslatableInterface` in `IdentityTranslator` (VincentLanglet) + * bug #61117 [Validator] fix handling required options (xabbuh) + * bug #61121 [DependencyInjection] Fix proxying services defined with an abstract class and a factory (nicolas-grekas) + * bug #61120 [DoctrineBridge] Prevent idle connection listener from running on subrequest (a.dmitryuk, dmitryuk) + * bug #61106 Fix `@var` phpdoc (fabpot) + * bug #61091 [Lock] [MongoDB] Enforce readPreference=primary and writeConcern=majority (notrix) + * bug #61105 [FrameworkBundle] fix phpdoc in `MicroKernelTrait` (santysisi) + * bug #61014 [TypeInfo] Reuse `CollectionType::mergeCollectionValueTypes` for `ConstFetchNode` (norkunas) + * bug #61076 [ExpressionLanguage] Fix dumping of null safe operator (ivantsepp) + * bug #60856 [ObjectMapper] handle non existing property errors (soyuka) + * bug #60802 [JsonPath] Improve escape sequence validation in name selector (alexandre-daubois) + * bug #60741 [Scheduler] Fix `#[AsCronTask]` not passing arguments to command (Jan Pintr, jan-pintr) + * bug #61056 [Validator] Allow mixed root on `CompoundConstraintTestCase` validator (thePanz) + * bug #61028 [Serializer] Fix `readonly` property initialization from incorrect scope (santysisi) + * bug #61073 [VarExporter] Dump implicit-nullable types as explicit to prevent the corresponding deprecation (nicolas-grekas) + * bug #61062 [Brevo Mailer] Webhook IP Addresses have changed (richardhj) + * bug #61004 [TypeInfo] Fix imported-only alias resolving (mtarld) + * bug #60975 [Form] Fix precision loss when rounding large integers in `NumberToLocalizedStringTransformer` (OskarStark) + * bug #61001 [JsonStreamer] Fix nested generated foreach loops (mttsch) + * bug #61036 [ObjectMapper] Correctly manage constructor initialization (alanpoulain) + * bug #60953 [DoctrineBridge] Restore compatibility with Doctrine ODM (pepeh) + * bug #61020 [Doctrine][FrameworkBundle][Serializer][Validator] Increase minimum version of type-info component (mitelg) + * bug #61031 [HttpClient] return early if handle has been cleaned up before (xabbuh) + * bug #60998 [TwigBridge] fix command option mode (`InputOption::VALUE_REQUIRED`) (gharlan) + * bug #60961 [TypeInfo] Fix `Type::fromValue` with empty array (norkunas) + * bug #60956 [TypeInfo] Fix `Type::fromValue` incorrectly setting object type instead of enum (norkunas) + * bug #60958 [Serializer] remove return type from `AbstractObjectNormalizer::getAllowedAttributes()` (xabbuh) + * bug #60507 [Console][Messenger] Fix: Allow `UnrecoverableExceptionInterface` to bypass retry in `RunCommandMessageHandler` (santysisi) + * 7.3.1 (2025-06-28) * bug #60044 [Console] Table counts wrong column width when using colspan and `setColumnMaxWidth()` (vladimir-vv) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3e7f5ec2b6e78..ac9a78cee91b3 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -11,8 +11,8 @@ The Symfony Connect username in parenthesis allows to get more information - Bernhard Schussek (bschussek) - Robin Chalas (chalas_r) - Tobias Schultze (tobion) - - Grégoire Pineau (lyrixx) - Alexandre Daubois (alexandre-daubois) + - Grégoire Pineau (lyrixx) - Thomas Calvet (fancyweb) - Christophe Coevoet (stof) - Wouter de Jong (wouterj) @@ -24,7 +24,6 @@ The Symfony Connect username in parenthesis allows to get more information - Ryan Weaver (weaverryan) - Jérémy DERUSSÉ (jderusse) - Jules Pietri (heah) - - Roland Franssen - Oskar Stark (oskarstark) - Johannes S (johannes) - Kris Wallsmith (kriswallsmith) @@ -45,12 +44,12 @@ The Symfony Connect username in parenthesis allows to get more information - Lukas Kahwe Smith (lsmith) - Hamza Amrouche (simperfit) - Martin Hasoň (hason) + - Mathias Arlaud (mtarld) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler - Jan Schädlich (jschaedl) - - Mathias Arlaud (mtarld) - Mathieu Lechat (mat_the_cat) - Simon André (simonandre) - Vincent Langlet (deviling) @@ -61,25 +60,23 @@ The Symfony Connect username in parenthesis allows to get more information - Grégoire Paris (greg0ire) - Alexandre Salomé (alexandresalome) - William DURAND - - ornicar - Dany Maillard (maidmaid) - - Eriksen Costa - Diego Saint Esteben (dosten) - - Dariusz Ruminski - - stealth35 ‏ (stealth35) - - Alexander Mols (asm89) - Gábor Egyed (1ed) - Francis Besset (francisbesset) - - Mathieu Santostefano (welcomattic) - - Titouan Galopin (tgalopin) + - Alexander Mols (asm89) + - stealth35 ‏ (stealth35) + - Eriksen Costa - Pierre du Plessis (pierredup) - - David Maicher (dmaicher) + - Titouan Galopin (tgalopin) + - Mathieu Santostefano (welcomattic) - Tomasz Kowalczyk (thunderer) + - David Maicher (dmaicher) - Bulat Shakirzyanov (avalanche123) - - Iltar van der Berg + - Alexander Schranz (alexander-schranz) - Miha Vrhovnik (mvrhov) + - Iltar van der Berg - Gary PEGEOT (gary-p) - - Alexander Schranz (alexander-schranz) - Saša Stamenković (umpirsky) - Allison Guilhem (a_guilhem) - Mathieu Piot (mpiot) @@ -87,986 +84,870 @@ The Symfony Connect username in parenthesis allows to get more information - Sarah Khalil (saro0h) - Laurent VOULLEMIER (lvo) - Konstantin Kudryashov (everzet) - - Guilhem N (guilhemn) - Bilal Amarni (bamarni) + - Guilhem N (guilhemn) - Eriksen Costa - - Florin Patan (florinpatan) + - Ruud Kamphuis (ruudk) - Vladimir Reznichenko (kalessil) - - Peter Rehm (rpet) + - Florin Patan (florinpatan) - Henrik Bjørnskov (henrikbjorn) - - Ruud Kamphuis (ruudk) - - David Buchmann (dbu) + - Peter Rehm (rpet) - Tomas Norkūnas (norkunas) - - Andrej Hudec (pulzarraider) + - David Buchmann (dbu) - Jáchym Toušek (enumag) + - Andrej Hudec (pulzarraider) + - Eric Clemmons (ericclemmons) - Hubert Lenoir (hubert_lenoir) - Christian Raue - - Eric Clemmons (ericclemmons) - - Denis (yethee) - - Alex Pott - Michel Weimerskirch (mweimerskirch) + - Matthias Schmidt + - Douglas Greenshields (shieldo) - Issei Murasawa (issei_m) + - Alex Pott - Arnout Boks (aboks) - - Douglas Greenshields (shieldo) - - Frank A. Fiebig (fafiebig) + - Denis (yethee) - Baldini - Fran Moreno (franmomu) + - Frank A. Fiebig (fafiebig) - Antoine Makdessi (amakdessi) - - Charles Sarrazin (csarrazi) - - Henrik Westphal (snc) - Dariusz Górecki (canni) + - Henrik Westphal (snc) + - Charles Sarrazin (csarrazi) + - Massimiliano Arione (garak) - Ener-Getick - Graham Campbell (graham) - Joel Wurtz (brouznouf) - - Massimiliano Arione (garak) - - Tugdual Saunier (tucksaun) - - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Tugdual Saunier (tucksaun) + - Lee McDermott - Phil E. Taylor (philetaylor) - - Konstantin Myakshin (koc) - - Daniel Holmes (dholmes) - Julien Falque (julienfalque) - - Toni Uebernickel (havvg) + - Konstantin Myakshin (koc) - Bart van den Burg (burgov) - - Vasilij Dusko | CREATION - Jordan Alliot (jalliot) - - Théo FIDRY - - John Wards (johnwards) + - Daniel Holmes (dholmes) + - Vasilij Dusko | CREATION + - Toni Uebernickel (havvg) - Valtteri R (valtzu) - Yanick Witschi (toflar) + - Théo FIDRY + - John Wards (johnwards) - Antoine Hérault (herzult) - Konstantin.Myakshin - - Jeroen Spee (jeroens) - - Arnaud Le Blanc (arnaud-lb) - - Sebastiaan Stok (sstok) - Maxime STEINHAUSSER - Rokas Mikalkėnas (rokasm) - Tac Tacelosky (tacman1123) - - gnito-org - - Tim Nagel (merk) - - Chris Wilkinson (thewilkybarkid) - - Jérôme Vasseur (jvasseur) - - Peter Kokot (peterkokot) + - Arnaud Le Blanc (arnaud-lb) + - matlec + - Jeroen Spee (jeroens) + - Sebastiaan Stok (sstok) - Brice BERNARD (brikou) + - Peter Kokot (peterkokot) + - Jérôme Vasseur (jvasseur) + - Chris Wilkinson (thewilkybarkid) + - Tim Nagel (merk) - Jacob Dreesen (jdreesen) - - Nicolas Philippe (nikophil) - - Martin Auswöger + - gnito-org - Michal Piotrowski - marc.weistroff - Lars Strojny (lstrojny) - - lenar - Vladimir Tsykun (vtsykun) + - Nicolas Philippe (nikophil) - Włodzimierz Gajda (gajdaw) - Javier Spagnoletti (phansys) - Adrien Brault (adrienbrault) - - Florent Morselli (spomky_) - soyuka - - Florian Voutzinos (florianv) - - Teoh Han Hui (teohhanhui) - - Przemysław Bogusz (przemyslaw-bogusz) + - Florent Morselli (spomky_) - Colin Frei - - excelwebzone + - Przemysław Bogusz (przemyslaw-bogusz) + - Teoh Han Hui (teohhanhui) + - Florian Voutzinos (florianv) + - Maxime Helias (maxhelias) - Paráda József (paradajozsef) - - Maximilian Beckers (maxbeckers) - Baptiste Clavié (talus) + - Maximilian Beckers (maxbeckers) - Alexander Schwenn (xelaris) - - Maxime Helias (maxhelias) - - Fabien Pennequin (fabienpennequin) - Dāvis Zālītis (k0d3r1s) - Gordon Franke (gimler) - - Malte Schlüter (maltemaltesich) - - jeremyFreeAgent (jeremyfreeagent) + - Fabien Pennequin (fabienpennequin) + - Vasilij Dusko - Michael Babker (mbabker) - - Alexis Lefebvre - - Hugo Alliaume (kocal) - Christopher Hertel (chertel) + - Hugo Alliaume (kocal) - Joshua Thijssen - - Vasilij Dusko + - jeremyFreeAgent (jeremyfreeagent) + - Malte Schlüter (maltemaltesich) + - Alexis Lefebvre - Daniel Wehner (dawehner) - - Robert Schönthal (digitalkaoz) - - Smaine Milianni (ismail1432) - - François-Xavier de Guillebon (de-gui_f) - Andreas Schempp (aschempp) - - noniagriconomie - Eric GELOEN (gelo) - Gabriel Caruso - - Stefano Sala (stefano.sala) - - Ion Bazan (ionbazan) - - Niels Keurentjes (curry684) + - Smaine Milianni (ismail1432) + - François-Xavier de Guillebon (de-gui_f) - OGAWA Katsuhiro (fivestar) + - Robert Schönthal (digitalkaoz) + - Ion Bazan (ionbazan) - Jhonny Lidfors (jhonne) - - Juti Noppornpitak (shiroyuki) + - Niels Keurentjes (curry684) + - Stefano Sala (stefano.sala) - Gregor Harlan (gharlan) - - Anthony MARTIN - Sebastian Hörl (blogsh) + - Hidenori Goto (hidenorigoto) + - Jonathan Scheiber (jmsche) + - Anthony MARTIN - Tigran Azatyan (tigranazatyan) - Florent Mata (fmata) - - Jonathan Scheiber (jmsche) - - Daniel Gomes (danielcsgomes) - - Hidenori Goto (hidenorigoto) - - Thomas Landauer (thomas-landauer) - Arnaud Kleinpeter (nanocom) - - Guilherme Blanco (guilhermeblanco) + - Juti Noppornpitak (shiroyuki) - David Prévot (taffit) - - Saif Eddin Gmati (azjezz) - - Farhad Safarov (safarov) - - SpacePossum - - Richard van Laak (rvanlaak) - - Andreas Braun - - Pablo Godel (pgodel) + - Guilherme Blanco (guilhermeblanco) + - Thomas Landauer (thomas-landauer) + - Daniel Gomes (danielcsgomes) - Alessandro Chitolina (alekitto) - - Jan Rosier (rosier) + - jwdeitch - Rafael Dohms (rdohms) + - Pablo Godel (pgodel) + - Saif Eddin Gmati (azjezz) + - Jan Rosier (rosier) + - Richard van Laak (rvanlaak) + - Farhad Safarov (safarov) - Roman Martinuk (a2a4) - - jwdeitch - - Jérôme Parmentier (lctrs) - - Ahmed TAILOULOUTE (ahmedtai) - - Simon Berger - - Jérémy Derussé - - Matthieu Napoli (mnapoli) - - Bob van de Vijver (bobvandevijver) - Tomas Votruba (tomas_votruba) - Arman Hosseini (arman) - - Sokolov Evgeniy (ewgraf) - Andréia Bohner (andreia) - - Tom Van Looy (tvlooy) - - Vyacheslav Pavlov + - Sokolov Evgeniy (ewgraf) - Albert Casademont (acasademont) - - George Mponos (gmponos) + - Jérémy Derussé + - Matthieu Napoli (mnapoli) - Richard Shank (iampersistent) - - Roland Franssen :) + - Ahmed TAILOULOUTE (ahmedtai) + - Bob van de Vijver (bobvandevijver) + - George Mponos (gmponos) - Fritz Michael Gschwantner (fritzmg) - - Romain Monteil (ker0x) - - Sergey (upyx) + - Roland Franssen + - Vyacheslav Pavlov + - Jérôme Parmentier (lctrs) + - Simon Berger + - Tom Van Looy (tvlooy) + - Alessandro Lai (jean85) + - Daniel Burger + - Jannik Zschiesche + - Jesse Rushlow (geeshoe) - Marco Pivetta (ocramius) - - Antonio Pauletich (x-coder264) - Vincent Touzet (vincenttouzet) - - Fabien Bourigault (fbourigault) - - Olivier Dolbeau (odolbeau) - - Rouven Weßling (realityking) - - Daniel Burger - - Ben Davies (bendavies) - - YaFou - - Guillaume (guill) + - Antonio Pauletich (x-coder264) + - Samuel NELA (snela) + - Tyson Andre - Clemens Tolboom - - Oleg Voronkovich - - Helmer Aaviksoo - - Alessandro Lai (jean85) - - 77web - - Gocha Ossinkine (ossinkine) - - matlec - - Jesse Rushlow (geeshoe) - - Matthieu Ouellette-Vachon (maoueh) - - Michał Pipa (michal.pipa) - - Dawid Nowak - Philipp Wahala (hifi) - - Jannik Zschiesche - - Amal Raghav (kertz) + - Matthieu Ouellette-Vachon (maoueh) + - Gocha Ossinkine (ossinkine) + - Stiven Llupa (sllupa) + - Fabien Bourigault (fbourigault) - Jonathan Ingram + - Ben Davies (bendavies) + - Rouven Weßling (realityking) + - Olivier Dolbeau (odolbeau) + - Sergey (upyx) - Artur Kotyrba + - 77web - Wouter J - - Tyson Andre + - Romain Monteil (ker0x) - GDIBass - - Samuel NELA (snela) - - Baptiste Leduc (korbeil) - - Vincent AUBERT (vincent) - - Nate Wiebe (natewiebe13) + - Dawid Nowak + - YaFou + - Oleg Voronkovich + - Guillaume (guill) + - Amal Raghav (kertz) + - Michał Pipa (michal.pipa) + - Marko Kaznovac (kaznovac) + - wkania + - Sergey Linnik (linniksa) - Michael Voříšek + - Arnaud PETITPAS (apetitpa) + - Asis Pattisahusiwa - zairig imad (zairigimad) - - Colin O'Dell (colinodell) - - Sébastien Alfaiate (seb33300) - - James Halsall (jaitsu) - - Christian Scheb - Alex Hofbauer (alexhofbauer) - - Mikael Pajunen - - Warnar Boekkooi (boekkooi) - - Justin Hileman (bobthecow) - - Anthony GRASSIOT (antograssiot) - - Dmitrii Chekaliuk (lazyhammer) - - Clément JOBEILI (dator) - - Andreas Möller (localheinz) - - Marek Štípek (maryo) - - Daniel Espendiller - - Arnaud PETITPAS (apetitpa) - Michael Käfer (michael_kaefer) - - Dorian Villet (gnutix) - - Martin Hujer (martinhujer) - - Sergey Linnik (linniksa) - - Richard Miller + - Nate Wiebe (natewiebe13) - Quynh Xuan Nguyen (seriquynh) - - Victor Bocharsky (bocharsky_bw) - - Asis Pattisahusiwa - - Aleksandar Jakovljevic (ajakov) - - Mario A. Alvarez Garcia (nomack84) - - Thomas Rabaix (rande) - D (denderello) - - DQNEO + - Anthony GRASSIOT (antograssiot) + - Mario A. Alvarez Garcia (nomack84) + - Christian Scheb + - Indra Gunawan (indragunawan) + - Colin O'Dell (colinodell) + - Thomas Rabaix (rande) + - Martin Hujer (martinhujer) + - Dmitrii Chekaliuk (lazyhammer) + - Vincent AUBERT (vincent) - Chi-teck - - Marko Kaznovac (kaznovac) - - Stiven Llupa (sllupa) - - Andre Rømcke (andrerom) - - Bram Leeda (bram123) - - Patrick Landolt (scube) - - Karoly Gossler (connorhu) + - Aleksandar Jakovljevic (ajakov) + - Larry Garfield (crell) + - Richard Miller + - Warnar Boekkooi (boekkooi) + - Justin Hileman (bobthecow) + - Baptiste Leduc (korbeil) + - Daniel Espendiller + - James Halsall (jaitsu) + - DQNEO + - Clément JOBEILI (dator) + - Sébastien Alfaiate (seb33300) + - Marek Štípek (maryo) + - Andreas Möller (localheinz) + - Mikael Pajunen + - Dorian Villet (gnutix) + - Victor Bocharsky (bocharsky_bw) + - Stepan Anchugov (kix) + - Filippo Tessarotto (slamdunk) - Timo Bakx (timobakx) - - Quentin Devos - - Giorgio Premi - - Alan Poulain (alanpoulain) - - Ruben Gonzalez (rubenrua) - - Benjamin Dulau (dbenjamin) - Markus Fasselt (digilist) - Denis Brumann (dbrumann) - - mcfedr (mcfedr) - - Loick Piera (pyrech) - - Remon van de Kamp - - Mathieu Lemoine (lemoinem) - - Christian Schmidt - Andreas Hucks (meandmymonkey) - - Artem Lopata - - Indra Gunawan (indragunawan) - - Noel Guilbert (noel) - - Bastien Jaillot (bastnic) - - Soner Sayakci - - Stadly - - Stepan Anchugov (kix) + - Nikolay Labinskiy (e-moe) + - Santiago San Martin (santysisi) - bronze1man + - Pierre Minnieur (pminnieur) + - Bastien Jaillot (bastnic) + - Andre Rømcke (andrerom) + - Guilliam Xavier - sun (sun) - - Filippo Tessarotto (slamdunk) - - Larry Garfield (crell) - Leo Feyer - - Nikolay Labinskiy (e-moe) - - Martin Schuhfuß (usefulthink) + - Giorgio Premi + - Mathieu Lemoine (lemoinem) + - Stadly + - Ruben Gonzalez (rubenrua) + - Remon van de Kamp + - Patrick Landolt (scube) + - Bram Leeda (bram123) + - Christian Schmidt + - Noel Guilbert (noel) - apetitpa - - wkania - - Guilliam Xavier - - Pierre Minnieur (pminnieur) - - Dominique Bongiraud - - Hugo Monteiro (monteiro) - - Dmitrii Poddubnyi (karser) - - Julien Pauli - - Jonathan H. Wage - - Michael Lee (zerustech) + - Karoly Gossler (connorhu) + - Alan Poulain (alanpoulain) + - mcfedr (mcfedr) + - Benjamin Dulau (dbenjamin) + - Loick Piera (pyrech) + - Martin Schuhfuß (usefulthink) + - Quentin Devos + - François Pluchino (francoispluchino) + - Maciej Malarz (malarzm) + - Edi Modrić (emodric) + - Mantis Development + - Sven Paulus (subsven) + - Dustin Whittle (dustinwhittle) + - Priyadi Iman Nurcahyo (priyadi) + - Arjen van der Meijden - Florian Lonqueu-Brochard (florianlb) - - Joe Bennett (kralos) - - Leszek Prabucki (l3l0) - - Wojciech Kania - - Thomas Lallement (raziel057) + - Jonathan H. Wage - Yassine Guedidi (yguedidi) - - François Zaninotto (fzaninotto) - - Dustin Whittle (dustinwhittle) - - Timothée Barray (tyx) - - jeff + - Tristan Darricau (tristandsensio) - John Kary (johnkary) - - Võ Xuân Tiến (tienvx) - fd6130 (fdtvui) - - Antonio J. García Lagar (ajgarlag) - - Priyadi Iman Nurcahyo (priyadi) + - Jan Sorgalla (jsor) + - Jérémie Augustin (jaugustin) - Oleg Andreyev (oleg.andreyev) - - Maciej Malarz (malarzm) - - Marcin Sikoń (marphi) - - Michele Orselli (orso) - - Arjen van der Meijden - - Sven Paulus (subsven) + - Võ Xuân Tiến (tienvx) + - Evert Harmeling (evertharmeling) + - Julien Brochet + - Joe Bennett (kralos) - Peter Kruithof (pkruithof) + - Pascal Montoya + - Wojciech Kania + - jeff + - Michele Orselli (orso) + - Timothée Barray (tyx) - Maxime Veber (nek-) - - Valentine Boineau (valentineboineau) - - Rui Marinho (ruimarinho) + - Marcin Sikoń (marphi) + - Thomas Lallement (raziel057) + - Leszek Prabucki (l3l0) - Jeroen Noten (jeroennoten) - - Possum - - Jérémie Augustin (jaugustin) - - Edi Modrić (emodric) - - Pascal Montoya - - Julien Brochet - - François Pluchino (francoispluchino) - - W0rma - - Tristan Darricau (tristandsensio) - - Jan Sorgalla (jsor) - henrikbjorn + - Antonio J. García Lagar (ajgarlag) + - Rui Marinho (ruimarinho) + - François Zaninotto (fzaninotto) + - Hugo Monteiro (monteiro) + - Valentine Boineau (valentineboineau) + - Michael Lee (zerustech) - Marcel Beerta (mazen) - - Evert Harmeling (evertharmeling) - - Mantis Development - - Hidde Wieringa (hiddewie) - - dFayet + - Dmitrii Poddubnyi (karser) + - jdhoek + - Philipp Cordes (corphi) + - Sullivan SENECHAL (soullivaneuh) + - Sylvain Fabre (sylfabre) + - Michel Roca (mroca) + - Chekote + - maxime.steinhausser - Rob Frawley 2nd (robfrawley) - - Renan (renanbr) - - Nikita Konstantinov (unkind) - - Dariusz - - Daniel Gorgan - - Francois Zaninotto + - Tim Goudriaan (codedmonkey) + - Elnur Abdurrakhimov (elnur) + - javaDeveloperKid - Aurélien Pillevesse (aurelienpillevesse) + - Ray + - Anderson Müller - Daniel Tschinder - - Christian Schmidt - - Alexander Kotynia (olden) - - Matthieu Lempereur (mryamous) - - Elnur Abdurrakhimov (elnur) + - Hidde Wieringa (hiddewie) - Manuel Reinhard (sprain) - - Zan Baldwin (zanbaldwin) - - Tim Goudriaan (codedmonkey) - - BoShurik - - Adam Prager (padam87) - - Benoît Burnichon (bburnichon) - - maxime.steinhausser - - Iker Ibarguren (ikerib) - - Roman Ring (inori) - - Xavier Montaña Carreras (xmontana) - - Romaric Drigon (romaricdrigon) - - Sylvain Fabre (sylfabre) - - Xavier Perez - - Arjen Brouwer (arjenjb) - - Patrick McDougle (patrick-mcdougle) - - Arnt Gulbrandsen - - Michel Roca (mroca) - - Marc Weistroff (futurecat) - - Michał (bambucha15) - - Danny Berger (dpb587) - - Alif Rachmawadi - - Anton Chernikov (anton_ch1989) - - Pierre-Yves Lebecq (pylebecq) - - Benjamin Leveque (benji07) - - Jordan Samouh (jordansamouh) - - David Badura (davidbadura) - - Sullivan SENECHAL (soullivaneuh) + - Adrian Rudnik (kreischweide) + - Nikita Konstantinov (unkind) + - Matthieu Lempereur (mryamous) - Uwe Jäger (uwej711) - - javaDeveloperKid - - Chris Smith (cs278) - - Lynn van der Berg (kjarli) - - Michaël Perrin (michael.perrin) + - Jurica Vlahoviček (vjurica) - Eugene Leonovich (rybakit) + - Zan Baldwin (zanbaldwin) + - Fabien S (bafs) - Joseph Rouff (rouffj) + - Xavier Perez + - Roman Ring (inori) + - Xavier Montaña Carreras (xmontana) + - Bob den Otter (bopp) - Félix Labrecque (woodspire) - Marvin Petker - GordonsLondon - - Ray - - Philipp Cordes (corphi) - - Fabien S (bafs) - - Chekote + - David Badura (davidbadura) + - Michaël Perrin (michael.perrin) - Thomas Adam - - Anderson Müller - - jdhoek - - Jurica Vlahoviček (vjurica) - - Bob den Otter (bopp) + - Romaric Drigon (romaricdrigon) + - Pierre-Yves Lebecq (pylebecq) + - Dariusz Ruminski + - Danny Berger (dpb587) + - Daniel Gorgan + - Benjamin Leveque (benji07) + - Michał (bambucha15) + - Marc Weistroff (futurecat) + - Renan (renanbr) + - dFayet - Thomas Schulz (king2500) + - Francois Zaninotto + - Christian Schmidt + - Arjen Brouwer (arjenjb) + - Alexander Kotynia (olden) + - Arnt Gulbrandsen + - BoShurik + - Adam Prager (padam87) + - Benoît Burnichon (bburnichon) + - Lynn van der Berg (kjarli) + - Alif Rachmawadi + - Jordan Samouh (jordansamouh) - Kyle - - Dariusz Rumiński - - Philippe SEGATORI (tigitz) - - Frank de Jonge - - Andrii Bodnar - - Dane Powell - - Sebastien Morel (plopix) - - Christopher Davis (chrisguitarguy) - - Loïc Frémont (loic425) - - Matthieu Auger (matthieuauger) + - Iker Ibarguren (ikerib) + - Patrick McDougle (patrick-mcdougle) + - Chris Smith (cs278) + - Anton Chernikov (anton_ch1989) - Sergey Belyshkin (sbelyshkin) - - Kévin THERAGE (kevin_therage) - - Herberto Graca - - Yoann RENARD (yrenard) - - Josip Kruslin (jkruslin) - - renanbr - - Sébastien Lavoie (lavoiesl) - - Alex Rock (pierstoval) - - Wodor Wodorski - - Beau Simensen (simensen) - - Magnus Nordlander (magnusnordlander) + - Warxcell (warxcell) + - jaugustin + - Dominique Bongiraud + - Florian Klein (docteurklein) + - Damien Alexandre (damienalexandre) + - Bertrand Zuchuat (garfield-fr) + - Baptiste Lafontaine (magnetik) - Robert Kiss (kepten) + - Serkan Yildiz (srknyldz) + - Alex Rock (pierstoval) - Alexandre Quercia (alquerci) + - Matthieu Auger (matthieuauger) + - Andrew Moore (finewolf) + - Mathieu Rochette (mathroc) - Marcos Sánchez + - Jordane VASPARD (elementaire) + - Pavel Batanov (scaytrase) + - Thomas Bisignani (toma) + - Andrii Bodnar + - Simon Podlipsky (simpod) - Emanuele Panzeri (thepanz) - - Zmey - - Santiago San Martin (santysisi) + - janschoenherr - Kim Hemsø Rasmussen (kimhemsoe) - - Maximilian Reichel (phramz) + - Loïc Frémont (loic425) - Samaël Villette (samadu61) - - jaugustin - Pascal Luna (skalpa) + - Marc Morera (mmoreram) + - Cédric Anne - Wouter Van Hecke - - Baptiste Lafontaine (magnetik) - - Michael Hirschler (mvhirsch) + - Beau Simensen (simensen) - Michael Holm (hollo) - - Robert Meijers - - roman joly (eltharin) - Blanchon Vincent (blanchonvincent) - - Cédric Anne - Christian Schmidt + - Atsuhiro KUBO (iteman) + - Emanuele Gaspari (inmarelibero) - Ben Hakim - Marco Petersen (ocrampete16) + - Lee Rowlands + - Christopher Davis (chrisguitarguy) + - Gustavo Piltcher - Bohan Yang (brentybh) - - Vilius Grigaliūnas - - Jordane VASPARD (elementaire) - - Thomas Bisignani (toma) - - Florian Klein (docteurklein) - - Pierre Ambroise (dotordu) - - Raphaël Geffroy (raphael-geffroy) - - Damien Alexandre (damienalexandre) + - Jan Decavele (jandc) + - Jerzy Zawadzki (jzawadzki) + - Aurelijus Valeiša (aurelijus) + - Emmanuel BORGES + - Craig Duncan (duncan3dc) - Manuel Kießling (manuelkiessling) - - Alexey Kopytko (sanmai) - - Warxcell (warxcell) - - SiD (plbsid) - - Atsuhiro KUBO (iteman) - - rudy onfroy (ronfroy) - - Serkan Yildiz (srknyldz) - - Andrew Moore (finewolf) - - Bertrand Zuchuat (garfield-fr) - - Marc Morera (mmoreram) - Gabor Toth (tgabi333) - - realmfoo - Joppe De Cuyper (joppedc) - - Simon Podlipsky (simpod) - - Thomas Tourlourat (armetiz) - - Andrey Esaulov (andremaha) - - Grégoire Passault (gregwar) - - Jerzy Zawadzki (jzawadzki) - - Ismael Ambrosi (iambrosi) - - Craig Duncan (duncan3dc) - - Emmanuel BORGES - - Mathieu Rochette (mathroc) - Karoly Negyesi (chx) - - Aurelijus Valeiša (aurelijus) - - Jan Decavele (jandc) - - Gustavo Piltcher - - Lee Rowlands + - Vilius Grigaliūnas + - Philippe SEGATORI (tigitz) + - Sébastien Lavoie (lavoiesl) + - Michael Hirschler (mvhirsch) + - realmfoo - Stepan Tanasiychuk (stfalcon) + - Raphaël Geffroy (raphael-geffroy) + - Herberto Graca + - Ismael Ambrosi (iambrosi) + - renanbr + - Grégoire Passault (gregwar) + - roman joly (eltharin) + - Andrey Esaulov (andremaha) + - Frank de Jonge + - Josip Kruslin (jkruslin) + - Kévin THERAGE (kevin_therage) - Ivan Kurnosov + - Pierre Ambroise (dotordu) + - rudy onfroy (ronfroy) + - Maximilian Reichel (phramz) + - Francesc Rosàs (frosas) + - Benjamin Morel - Tiago Ribeiro (fixe) + - Sebastien Morel (plopix) + - Magnus Nordlander (magnusnordlander) + - Dane Powell + - Thomas Tourlourat (armetiz) + - SiD (plbsid) + - Alexey Kopytko (sanmai) - Raul Fraile (raulfraile) - - Adrian Rudnik (kreischweide) - - Pavel Batanov (scaytrase) - - Francesc Rosàs (frosas) - - Bongiraud Dominique - - janschoenherr - - Emanuele Gaspari (inmarelibero) + - Jack Worman (jworman) + - Yoann RENARD (yrenard) + - Wodor Wodorski + - Pavel Volokitin (pvolok) + - Ivan Mezinov + - Erin Millard + - Hamza Makraz (makraz) + - Zmey - Artem (artemgenvald) + - ivan + - Lukáš Holeczy (holicz) + - SUMIDA, Ippei (ippey_s) - Thierry T (lepiaf) - Lorenz Schori - - Lukáš Holeczy (holicz) - Jeremy Livingston (jeremylivingston) - - ivan - - SUMIDA, Ippei (ippey_s) + - Nicolas LEFEVRE (nicoweb) + - Roumen Damianoff - Urinbayev Shakhobiddin (shokhaa) - Ahmed Raafat - - Philippe Segatori - - Thibaut Cheymol (tcheymol) - - Vincent Chalamon - - Raffaele Carelle - - Erin Millard - - Matthew Lewinski (lewinski) - Islam Israfilov (islam93) - - Ricard Clau (ricardclau) - - Roumen Damianoff - Thomas Royer (cydonia7) - - Nicolas LEFEVRE (nicoweb) + - Harm van Tilborg (hvt) + - Haralan Dobrev (hkdobrev) + - Gonzalo Vilaseca (gonzalovilaseca) + - Francesco Levorato + - smoench - Asmir Mustafic (goetas) + - Tobias Sjösten (tobiassjosten) - Mateusz Sip (mateusz_sip) - - Francesco Levorato + - C (dagardner) + - Dalibor Karlović - Vitaliy Zakharov (zakharovvi) - - Tobias Sjösten (tobiassjosten) + - Inal DJAFAR (inalgnu) - Gyula Sallai (salla) + - Johann Pardanaud - Hendrik Luup (hluup) - - Inal DJAFAR (inalgnu) - - C (dagardner) + - Pierre Rineau + - mondrake (mondrake) - Martin Herndl (herndlm) + - Yaroslav Kiliba - Dmytro Borysovskyi (dmytr0) - - Johann Pardanaud - - Pierre Rineau - - Kai Dederichs - Pavel Kirpitsov (pavel-kirpichyov) - - Artur Eshenbrener - - Issam Raouf (iraouf) - - Harm van Tilborg (hvt) - Thomas Perez (scullwm) - Gwendolen Lynch - - smoench - Felix Labrecque - - mondrake (mondrake) - - Yaroslav Kiliba - FORT Pierre-Louis (plfort) - - Jan Böhmer - Terje Bråten - - Gonzalo Vilaseca (gonzalovilaseca) - Tarmo Leppänen (tarlepp) - Jakub Kucharovic (jkucharovic) - Daniel STANCU - Kristen Gilden - Robbert Klarenbeek (robbertkl) - - Dalibor Karlović - - Hamza Makraz (makraz) - Eric Masoero (eric-masoero) - Vitalii Ekert (comrade42) - Clara van Miert - - Haralan Dobrev (hkdobrev) - hossein zolfi (ocean) - - Alexander Menshchikov - - Clément Gautier (clementgautier) - James Gilliland (neclimdul) - - Sanpi (sanpi) - - Eduardo Gulias (egulias) - - giulio de donato (liuggio) - - Ivan Mezinov + - Kirill chEbba Chebunin + - Nathanael Noblet (gnat) - ShinDarth - - Stéphane PY (steph_py) + - giulio de donato (liuggio) + - Marek Kalnik (marekkalnik) + - Matthias Althaus (althaus) + - Eduardo Gulias (egulias) - Cătălin Dan (dancatalin) - - Philipp Kräutli (pkraeutli) - - Rhodri Pugh (rodnaph) + - Dimitri Gritsajuk (ottaviano) + - Daniel Tschinder + - Stéphane PY (steph_py) - BrokenSourceCode + - Alex (aik099) + - Rhodri Pugh (rodnaph) - Grzegorz (Greg) Zdanowski (kiler129) - - Dimitri Gritsajuk (ottaviano) - - Kirill chEbba Chebunin - Pol Dellaiera (drupol) - - Alex (aik099) + - Clément Gautier (clementgautier) - Kieran Brahney + - Sanpi (sanpi) - Fabien Villepinte + - Vyacheslav Salakhutdinov (megazoll) - Greg Thornton (xdissent) - Alex Bowers + - Gasan Guseynov (gassan) + - Philipp Kräutli (pkraeutli) - Kev - kor3k kor3k (kor3k) - Costin Bereveanu (schniper) - - Andrii Dembitskyi - - Gasan Guseynov (gassan) - - Marek Kalnik (marekkalnik) - - Vyacheslav Salakhutdinov (megazoll) - Maksym Slesarenko (maksym_slesarenko) - Marc Biorklund (mbiork) - - Hassan Amouhzi - - Tamas Szijarto - Michele Locati - - Yannick Ihmels (ihmels) - - Pavel Volokitin (pvolok) - Arthur de Moulins (4rthem) - - Matthias Althaus (althaus) - - Saif Eddin G - - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer - Ivan Sarastov (isarastov) - flack (flack) - Shein Alexey - - Link1515 - Joe Lencioni - - Daniel Tschinder - - Diego Agulló (aeoris) - vladimir.reznichenko + - Albert Jessurum (ajessu) - Kai - - Alain Hippolyte (aloneh) - Grenier Kévin (mcsky_biig) - Xavier HAUSHERR - - Albert Jessurum (ajessu) - - Romain Pierre - - Laszlo Korte - Alessandro Desantis - hubert lecorche (hlecorche) - Vladyslav Loboda - Marc Morales Valldepérez (kuert) + - Karel Souffriau - Vadim Kharitonov (vadim) - Oscar Cubo Medina (ocubom) - - Karel Souffriau + - Alain Hippolyte (aloneh) - Christophe L. (christophelau) - - a.dmitryuk - - Anthon Pang (robocoder) - Julien Galenski (ruian) - - Benjamin Morel - Ben Scott (bpscott) - - Shyim - Pablo Lozano (arkadis) - - Brian King - - quentin neyrat (qneyrat) - - Chris Tanaskoski (devristo) - - Steffen Roßkamp - - Andrey Lebedev (alebedev) - - Alexandru Furculita (afurculita) - - Michel Salib (michelsalib) - - Ben Roberts (benr77) - - Ahmed Ghanem (ahmedghanem00) - - Valentin Jonovs - - geoffrey - - Quentin Dequippe (qdequippe) - - Benoit Galati (benoitgalati) - - Benjamin (yzalis) - - Jeanmonod David (jeanmonod) - - Webnet team (webnet) - - Christian Gripp (core23) - - Tobias Bönner - - Nicolas Rigaud - - PHAS Developer - - Ben Ramsey (ramsey) - - Berny Cantos (xphere81) - - Antonio Jose Cerezo (ajcerezo) - - Maelan LE BORGNE - - Thomas Talbot (ioni) - - Marcin Szepczynski (czepol) - - Lescot Edouard (idetox) - - Dennis Fridrich (dfridrich) - - Mohammad Emran Hasan (phpfour) - - Florian Merle (florian-merle) - - Dmitriy Mamontov (mamontovdmitriy) - - Jan Schumann - - Matheo Daninos (mathdns) - - Neil Peyssard (nepey) - - Niklas Fiekas - - Mark Challoner (markchalloner) - - Andreas Hennings - - Markus Bachmann (baachi) - - Gunnstein Lye (glye) - - Erkhembayar Gantulga (erheme318) - - Yi-Jyun Pan - - Sergey Melesh (sergex) - - Greg Anderson - - Arnaud De Abreu (arnaud-deabreu) - - lancergr - - Benjamin Zaslavsky (tiriel) - - Tri Pham (phamuyentri) - - Angelov Dejan (angelov) - - Ivan Nikolaev (destillat) - - Gildas Quéméner (gquemener) - - Ioan Ovidiu Enache (ionutenache) - - Mokhtar Tlili (sf-djuba) - - Maxim Dovydenok (dovydenok-maxim) - - Laurent Masforné (heisenberg) - - Claude Khedhiri (ck-developer) - - Benjamin Georgeault (wedgesama) - - Desjardins Jérôme (jewome62) - - Arturs Vonda - - Matthew Smeets - - Toni Rudolf (toooni) - - Stefan Gehrig (sgehrig) - - vagrant - - Matthias Krauser (mkrauser) - - Benjamin Cremer (bcremer) - - Maarten de Boer (mdeboer) - - Asier Illarramendi (doup) - - AKeeman (akeeman) - - Martijn Cuppens - - Restless-ET - - Vlad Gregurco (vgregurco) - - Artem Stepin (astepin) - - Jérémy DECOOL (jdecool) - - Boris Vujicic (boris.vujicic) - - Dries Vints - - Judicaël RUFFIEUX (axanagor) - - Chris Sedlmayr (catchamonkey) - - DerManoMann - - Jérôme Tanghe (deuchnord) - - Mathias STRASSER (roukmoute) - - simon chrzanowski (simonch) - - Kamil Kokot (pamil) - - Seb Koelen + - Laszlo Korte + - Diego Agulló (aeoris) + - Valmonzo + - Matthew Lewinski (lewinski) + - Soner Sayakci + - Jan Böhmer + - Hassan Amouhzi + - a.dmitryuk + - Yannick Ihmels (ihmels) + - Endre Fejes + - Vincent Chalamon + - Philippe Segatori + - Raffaele Carelle + - Link1515 + - Anthon Pang (robocoder) + - Thibaut Cheymol (tcheymol) + - Ricard Clau (ricardclau) + - Issam Raouf (iraouf) - Christoph Mewes (xrstf) - - Andrew M-Y (andr) - - Krasimir Bosilkov (kbosilkov) - - Marcin Michalski (marcinmichalski) - - Vitaliy Tverdokhlib (vitaliytv) - - Ariel Ferrandini (aferrandini) - - BASAK Semih (itsemih) - - Dirk Pahl (dirkaholic) - - Cédric Lombardot (cedriclombardot) - - Jérémy REYNAUD (babeuloula) - - Faizan Akram Dar (faizanakram) - - Arkadius Stefanski (arkadius) - - Andy Palmer (andyexeter) - - Jonas Flodén (flojon) - - AnneKir - - Tobias Weichart - - Arnaud POINTET (oipnet) - - Tristan Pouliquen - - Miro Michalicka - - Hans Mackowiak - - M. Vondano - - Dominik Zogg - - Maximilian Zumbansen - - Vadim Borodavko (javer) - - Tavo Nieves J (tavoniievez) - - Luc Vieillescazes (iamluc) - - Erik Saunier (snickers) - - François Dume (franek) - - Jerzy Lekowski (jlekowski) - - Raulnet - - Petrisor Ciprian Daniel - - Oleksiy (alexndlm) - - William Arslett (warslett) - - Giso Stallenberg (gisostallenberg) - - Rob Bast - - Roberto Espinoza (respinoza) - - Steven RENAUX (steven_renaux) - - Marvin Feldmann (breyndotechse) - - Soufian EZ ZANTAR (soezz) - - Marek Zajac - - Adam Harvey - - Klaus Silveira (klaussilveira) - - ilyes kooli (skafandri) - - Anton Bakai - - battye - - Nicolas Dousson - - Axel Guckelsberger (guite) - - Sam Fleming (sam_fleming) - - Alex Bakhturin - - Belhassen Bouchoucha (crownbackend) - - Patrick Reimers (preimers) - - Brayden Williams (redstar504) - - insekticid - - Jérémy M (th3mouk) - - Trent Steel (trsteel88) - - boombatower - - Alireza Mirsepassi (alirezamirsepassi) - - Jérôme Macias (jeromemacias) - - Andrey Astakhov (aast) - - ReenExe - - Fabian Lange (codingfabian) - - kylekatarnls (kylekatarnls) - - Yoshio HANAWA - - Jan van Thoor (janvt) - - Joshua Nye - - Martin Kirilov (wucdbm) - Koen Reiniers (koenre) - Kurt Thiemann - - Nathan Dench (ndenc2) - Gijs van Lammeren + - ilyes kooli (skafandri) + - Alireza Mirsepassi (alirezamirsepassi) - Sebastian Bergmann + - Giso Stallenberg (gisostallenberg) + - Adam Harvey - Nadim AL ABDOU (nadim) - Matthew Grasmick - - Miroslav Šustek (sustmi) - Pablo Díez (pablodip) - - Kevin McBride + - Romain Gautier (mykiwi) - Sergio Santoro - Jonas Elfering - - Philipp Rieber (bicpi) - - Dmitriy Derepko - - Manuel de Ruiter (manuel) - - Nathanael Noblet (gnat) - nikos.sotiropoulos - - BENOIT POLASZEK (bpolaszek) + - Yoshio HANAWA - Eduardo Oliveira (entering) - Oleksii Zhurbytskyi + - Bahman Mehrdad (bahman) - Bilge - - Anatoly Pashin (b1rdex) - - Jonathan Johnson (jrjohnson) - - Eugene Wissner - - Ricardo Oliveira (ricardolotr) - - Roy Van Ginneken (rvanginneken) - - ondrowan + - Trent Steel (trsteel88) - Barry vd. Heuvel (barryvdh) + - Ricardo Oliveira (ricardolotr) + - Jonathan Johnson (jrjohnson) + - Nicolas Dewez (nicolas_dewez) - Antonin CLAUZIER (0x346e3730) - - Chad Sikorra (chadsikorra) + - Jeroen Thora (bolle) + - Marek Zajac + - Markus Lanthaler (lanthaler) + - Greg ORIOL + - Leevi Graham (leevigraham) + - Zbigniew Malcherczyk (ferror) + - Roy Van Ginneken (rvanginneken) + - Nathan Dench (ndenc2) + - Denis Kulichkin (onexhovia) + - Adam Szaraniec + - Anatoly Pashin (b1rdex) + - Soufian EZ ZANTAR (soezz) + - Patrick Reimers (preimers) + - BENOIT POLASZEK (bpolaszek) + - Marvin Feldmann (breyndotechse) - Evan S Kaufman (evanskaufman) - mcben + - Klaus Silveira (klaussilveira) + - Roberto Espinoza (respinoza) + - Rob Bast + - Grummfy (grummfy) - Jérôme Vieilledent (lolautruche) - Roman Anasal - Filip Procházka (fprochazka) - Sergey Panteleev - - Jeroen Thora (bolle) - - Markus Lanthaler (lanthaler) - Gigino Chianese (sajito) - Remi Collet - Piotr Kugla (piku235) - Vicent Soria Durá (vicentgodella) - - Michael Moravec - - Leevi Graham (leevigraham) - Anthony Ferrara - tim - Ioan Negulescu - - Greg ORIOL - Jakub Škvára (jskvara) - Andrew Udvare (audvare) - siganushka (siganushka) - - alexpods - Quentin Schuler (sukei) - - Adam Szaraniec - Dariusz Ruminski - - Bahman Mehrdad (bahman) - - Romain Gautier (mykiwi) - Matthieu Bontemps - Erik Trapman - De Cock Xavier (xdecock) - - Zbigniew Malcherczyk (ferror) - - Nicolas Dewez (nicolas_dewez) - - Denis Kulichkin (onexhovia) - Scott Arciszewski - - Xavier HAUSHERR - - Norbert Orzechowicz (norzechowicz) - - Robert-Jan de Dreu - - Fabrice Bernhard (fabriceb) + - R. Achmad Dadang Nur Hidayanto (dadangnh) + - Bhavinkumar Nakrani (bhavin4u) - Matthijs van den Bos (matthijs) + - Peter Bowyer (pbowyer) - Markus S. (staabm) + - John Bafford (jbafford) - PatNowak - - Bhavinkumar Nakrani (bhavin4u) - - Jaik Dean (jaikdean) + - Samuele Lilli (doncallisto) + - Chad Sikorra (chadsikorra) + - William Arslett (warslett) + - Dave Hulbert (dave1010) + - Marcin Chyłek (songoq) - Krzysztof Piasecki (krzysztek) + - Oleksiy (alexndlm) + - Denis Gorbachev (starfall) + - Jerzy Lekowski (jlekowski) + - François Dume (franek) - Pavel Popov (metaer) + - Fabrice Bernhard (fabriceb) - Lenard Palko + - Jaik Dean (jaikdean) - Nils Adermann (naderman) + - Joachim Løvgaard (loevgaard) + - Tavo Nieves J (tavoniievez) + - Vadim Borodavko (javer) + - Maximilian Zumbansen + - Anton Bakai - Tom Klingenberg - Gábor Fási - - R. Achmad Dadang Nur Hidayanto (dadangnh) + - Gawain Lynch (gawain) + - Ivan Rey (ivanrey) - Nate (frickenate) - Stefan Kruppa - Jacek Jędrzejewski (jacek.jedrzejewski) - Shakhobiddin - - Stefan Kruppa - - Joachim Løvgaard (loevgaard) - sasezaki - Dawid Pakuła (zulusx) + - Dominik Zogg + - M. Vondano - Florian Rey (nervo) - - Peter Bowyer (pbowyer) - Rodrigo Borrego Bernabé (rodrigobb) - - John Bafford (jbafford) - - Emanuele Iannone - - Petr Duda (petrduda) - Marcos Rezende (rezende79) - - Denis Gorbachev (starfall) + - Petr Duda (petrduda) - Martin Morávek (keeo) - - Kevin Saliou (kbsali) - Steven Surowiec (steves) - Shawn Iwinski - - Dieter - - Samuele Lilli (doncallisto) - - Gawain Lynch (gawain) - mmokhi + - Kevin McBride - Ryan - Alexander Deruwe (aderuwe) - - Dave Hulbert (dave1010) - - Ivan Rey (ivanrey) - - Johan Vlaar (johjohan) + - Hans Mackowiak - M. (mbontemps) - - Marcin Chyłek (songoq) - Ned Schwartz - - Ziumin - Daniel Tiringer - - Lenar Lõhmus - Ilija Tovilo (ilijatovilo) - - Maxime Pinot (maximepinot) - Sander Toonen (xatoo) + - Guilherme Ferreira - Zach Badgett (zachbadgett) - Loïc Faugeron + - Miro Michalicka - Aurélien Fredouelle - Pavel Campr (pcampr) - - Andrii Dembitskyi - - Markus Staab - Forfarle (forfarle) - - Johnny Robeson (johnny) + - Yi-Jyun Pan + - Tobias Weichart + - Maxime Pinot (maximepinot) + - AnneKir + - W0rma + - Jonas Flodén (flojon) - Disquedur - - Guilherme Ferreira + - Andrii Dembitskyi - Geoffrey Tran (geoff) - Jannik Zschiesche - Bernd Stellwag - Jan Ole Behrens (deegital) - - wicliff wolda (wickedone) - - Mantas Var (mvar) - - Ramunas Pabreza (doobas) - - Yuriy Vilks (igrizzli) - - Terje Bråten - - Sebastian Krebs - - Piotr Stankowski - - Pierre-Emmanuel Tanguy (petanguy) - - Julien Maulny - - Gennadi Janzen - - johan Vlaar - - Paul Oms - - James Hemery - - wuchen90 - - Wouter van der Loop (toppy-hennie) - - Ninos - - julien57 - - Mátyás Somfai (smatyas) - - MrMicky - - Bastien DURAND (deamon) - - Dmitry Simushev - - alcaeus - - Simon Leblanc (leblanc_simon) - - Fred Cox - - Simon DELICATA - - Thibault Buathier (gwemox) - - Julien Boudry - - vitaliytv - - Franck RANAIVO-HARISOA (franckranaivo) - - Yi-Jyun Pan - - Egor Taranov - - Arnaud Frézet - - Philippe Segatori - - Jon Gotlin (jongotlin) - - Adrian Nguyen (vuphuong87) - - benjaminmal - - Roy de Vos Burchart - - Andrey Sevastianov - - Oleksandr Barabolia (oleksandrbarabolia) - - Khoo Yong Jun - - Christin Gruber (christingruber) - - Sebastian Blum - - Daniel González (daniel.gonzalez) - - Julien Turby - - Ricky Su (ricky) - - scyzoryck - - Kyle Evans (kevans91) - - Max Rath (drak3) - - Cristoforo Cervino (cristoforocervino) - - marie - - Stéphane Escandell (sescandell) - - Fractal Zombie - - James Johnston - - Noémi Salaün (noemi-salaun) - - Sinan Eldem (sineld) - - Gennady Telegin - - Benedikt Lenzen (demigodcode) - - ampaze - - Alexandre Dupuy (satchette) - - Michel Hunziker - - Malte Blättermann - - Ilya Levin (ilyachase) - - Simeon Kolev (simeon_kolev9) - - Joost van Driel (j92) - - Jonas Elfering - - Mihai Stancu - - Nahuel Cuesta (ncuesta) - - Chris Boden (cboden) - - EStyles (insidestyles) - - Christophe Villeger (seragan) - - Krystian Marcisz (simivar) - - Julien Fredon - - Xavier Leune (xleune) - - Hany el-Kerdany - - Wang Jingyu - - Baptiste CONTRERAS - - Åsmund Garfors - - Maxime Douailin - - Jean Pasdeloup - - Maxime COLIN (maximecolin) - - Loïc Ovigne (oviglo) - - Lorenzo Millucci (lmillucci) - - Javier López (loalf) - - Reinier Kip - - Jérôme Tamarelle (jtamarelle-prismamedia) - - Emil Masiakowski - - Geoffrey Brier (geoffrey-brier) - - Sofien Naas + - Markus Staab + - BASAK Semih (itsemih) + - Ariel Ferrandini (aferrandini) + - Johnny Robeson (johnny) + - Robert-Jan de Dreu + - Petrisor Ciprian Daniel + - Vitaliy Tverdokhlib (vitaliytv) + - Marcin Michalski (marcinmichalski) + - Cédric Lombardot (cedriclombardot) + - Krasimir Bosilkov (kbosilkov) + - Luc Vieillescazes (iamluc) + - Andrew M-Y (andr) + - Faizan Akram Dar (faizanakram) + - Martin Kirilov (wucdbm) + - Dirk Pahl (dirkaholic) + - Arkadius Stefanski (arkadius) + - Kamil Kokot (pamil) + - Raulnet + - simon chrzanowski (simonch) + - Chris Sedlmayr (catchamonkey) + - Arnaud POINTET (oipnet) + - Mathias STRASSER (roukmoute) + - Erik Saunier (snickers) + - Jérémy DECOOL (jdecool) + - DerManoMann + - Jérémy REYNAUD (babeuloula) + - Judicaël RUFFIEUX (axanagor) + - Andy Palmer (andyexeter) + - Dries Vints + - Boris Vujicic (boris.vujicic) + - Vlad Gregurco (vgregurco) + - Artem Stepin (astepin) + - Martijn Cuppens + - Asier Illarramendi (doup) + - Brayden Williams (redstar504) + - Maarten de Boer (mdeboer) + - Jérôme Tanghe (deuchnord) + - Benjamin Cremer (bcremer) + - vagrant + - Stefan Gehrig (sgehrig) + - Arturs Vonda + - Desjardins Jérôme (jewome62) + - Claude Khedhiri (ck-developer) + - Laurent Masforné (heisenberg) + - Maxim Dovydenok (dovydenok-maxim) + - Ioan Ovidiu Enache (ionutenache) + - Ivan Nikolaev (destillat) + - Emanuele Iannone + - Angelov Dejan (angelov) + - Tri Pham (phamuyentri) + - lancergr + - AKeeman (akeeman) + - Sergey Melesh (sergex) + - Arnaud De Abreu (arnaud-deabreu) + - Jérémy M (th3mouk) + - Erkhembayar Gantulga (erheme318) + - Neil Peyssard (nepey) + - Gunnstein Lye (glye) + - Toni Rudolf (toooni) + - Lescot Edouard (idetox) + - Andreas Hennings + - Matthias Krauser (mkrauser) + - Kevin Saliou (kbsali) + - Mark Challoner (markchalloner) + - Florian Merle (florian-merle) + - Niklas Fiekas + - Mohammad Emran Hasan (phpfour) + - Greg Anderson + - Markus Bachmann (baachi) + - Jan Schumann + - Dmitriy Mamontov (mamontovdmitriy) + - Benjamin Georgeault (wedgesama) + - Dennis Fridrich (dfridrich) + - Benjamin Zaslavsky (tiriel) + - Gildas Quéméner (gquemener) + - Restless-ET + - Mokhtar Tlili (sf-djuba) + - Ziumin + - Maelan LE BORGNE + - Berny Cantos (xphere81) + - PHAS Developer + - Thomas Talbot (ioni) + - Christian Gripp (core23) + - geoffrey + - Alexandru Furculita (afurculita) + - Johan Vlaar (johjohan) + - Chris Tanaskoski (devristo) + - quentin neyrat (qneyrat) + - Brian King + - Nicolas Rigaud + - Marcin Szepczynski (czepol) + - Valentin Jonovs + - Ben Ramsey (ramsey) + - Tobias Bönner + - Steffen Roßkamp + - Benjamin (yzalis) + - Ben Roberts (benr77) + - Antonio Jose Cerezo (ajcerezo) + - Webnet team (webnet) + - Ahmed Ghanem (ahmedghanem00) + - Andrey Lebedev (alebedev) + - Jeanmonod David (jeanmonod) + - Benoit Galati (benoitgalati) + - Quentin Dequippe (qdequippe) + - Matthew Smeets + - Michael Moravec + - Andrey Astakhov (aast) + - Eugene Wissner + - Norbert Orzechowicz (norzechowicz) + - lenar + - Xavier HAUSHERR + - Matheo Daninos (mathdns) + - battye + - Max Baldanza + - Steven RENAUX (steven_renaux) + - Philipp Rieber (bicpi) + - Manuel de Ruiter (manuel) + - Michel Salib (michelsalib) + - Jérôme Macias (jeromemacias) + - Axel Guckelsberger (guite) + - Alex Bakhturin + - Belhassen Bouchoucha (crownbackend) + - Sam Fleming (sam_fleming) + - Joshua Nye + - boombatower + - ReenExe + - Fabian Lange (codingfabian) + - kylekatarnls (kylekatarnls) + - Miroslav Šustek (sustmi) + - Jan van Thoor (janvt) - Alexandre Parent + - Sofien Naas - Daniel Badura + - Loïc Ovigne (oviglo) - Brajk19 + - Dustin Dobervich (dustin10) + - Martijn Evers - Roger Guasch (rogerguasch) + - Vladimir Varlamov (iamvar) - DT Inier (gam6itko) - - Dustin Dobervich (dustin10) - Luis Tacón (lutacon) - Dmitrii Tarasov (dtarasov) - - dantleech - Philipp Kolesnikov - - Jack Worman (jworman) - Sebastian Marek (proofek) - - Carlos Pereira De Amorim (epitre) - zenmate - - Andrii Popov (andrii-popov) - - David Fuhr - Malte Müns - Rodrigo Aguilera - - Vladimir Varlamov (iamvar) - Aurimas Niekis (gcds) - - Matthieu Calie (matth--) + - andrey1s + - Fabien Salles (blacked) - Sem Schidler (xvilo) - Benjamin Schoch (bschoch) - - Martins Sipenko - - Guilherme Augusto Henschel - Rostyslav Kinash + - Marc Abramowitz + - Rimas Kudelis - Christophe V. (cvergne) - Mardari Dorel (dorumd) - - Daisuke Ohata - Vincent Simonin - Pierrick VIGNAND (pierrick) - - Alex Bogomazov (alebo) - aaa2000 (aaa2000) - Andrew Neil Forster (krciga22) - Stefan Warman (warmans) @@ -1074,2108 +955,583 @@ The Symfony Connect username in parenthesis allows to get more information - Behnoush Norouzali (behnoush) - Marko H. Tamminen (gzumba) - Wesley Lancel - - Xavier Briand (xavierbriand) - - Ke WANG (yktd26) + - katario - Ivo Bathke (ivoba) + - Ke WANG (yktd26) + - 243083df + - Luca Saba (lucasaba) - Lukas Mencl + - Emil Einarsson + - Mickaël Isaert (misaert) - David Molineus - - Strate + - Gregor Nathanael Meyer (spackmat) + - Florent Viel (luxifer) - Anton A. Sumin - - Marko Petrovic + - Don Pinkster + - Miquel Rodríguez Telep (mrtorrent) + - Andreas Erhard (andaris) - alexandre.lassauge + - Guillaume Aveline - Israel J. Carberry - - Miquel Rodríguez Telep (mrtorrent) + - Michael Devery (mickadoo) - Tamás Nagy (t-bond) + - Kieran + - Robin van der Vleuten (robinvdvleuten) + - Kien Nguyen - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Mickaël Buliard (mbuliard) + - Michael Roterman (wtfzdotnet) + - Morten Wulff (wulff) - Jan Nedbal - Cornel Cruceru (amne) - Richard Bradley - Jan Walther (janwalther) - - Ulumuddin Cahyadi Yunus (joenoez) - rtek - - Mickaël Isaert (misaert) - Adrien Jourdier (eclairia) - Florian Pfitzer (marmelatze) + - Alaattin Kahramanlar (alaattin) - Ivan Grigoriev (greedyivan) + - ornicar - Johann Saunier (prophet777) - Kevin SCHNEKENBURGER - Geordie - - Fabien Salles (blacked) - Tim Düsterhus - - Andreas Erhard (andaris) - - alexpozzi - - Michael Devery (mickadoo) - - Gregor Nathanael Meyer (spackmat) - Antoine Corcy - Ahmed Ashraf (ahmedash95) - Gert Wijnalda (cinamo) - Aurimas Niekis (aurimasniekis) - - Luca Saba (lucasaba) - Sascha Grossenbacher (berdir) - - Guillaume Aveline - nathanpage + - _sir_kane (waly) - Robin Lehrmann - - Szijarto Tamas - Thomas P + - Steve Grunwell - Stephan Vock (glaubinix) - Jaroslav Kuba - - Benjamin Zikarsky (bzikarsky) - Kristijan Kanalaš (kristijan_kanalas_infostud) + - Benjamin Zikarsky (bzikarsky) - Rodrigo Méndez (rodmen) + - Oriol Viñals + - michaelwilliams + - Maks 3w (maks3w) - sl_toto (sl_toto) + - Sascha Dens (saschadens) + - Renan Gonçalves (renan_saddam) + - Matt Janssen - Marek Pietrzak (mheki) - “Filip - - Mickaël Andrieu (mickaelandrieu) + - Tristan Roussel + - RJ Garcia + - Jawira Portugal (jawira) + - Joschi Kuphal + - Oliver Hoff - Simon Watiau (simonwatiau) - - Ruben Jacobs (rubenj) + - Benjamin Grandfond (benjamin) - Simon Schick (simonsimcity) - - Tristan Roussel - - NickSdot + - Ruben Jacobs (rubenj) + - Toon Verwerft (veewee) + - Delf Tonder (leberknecht) + - Thomas Ploch - Niklas Keller - - Alexandre parent + - Douglas Hammond (wizhippo) - Cameron Porter - Hossein Bukhamsin - - Oliver Hoff - Christian Sciberras (uuf6429) - Thomas Nunninger - origaminal - Matteo Beccati (matteobeccati) - - Renan Gonçalves (renan_saddam) - Vitaliy Ryaboy (vitaliy) - Kevin (oxfouzer) - Paweł Wacławczyk (pwc) - Oleg Zinchenko (cystbear) - Baptiste Meyer (meyerbaptiste) - Tales Santos (tsantos84) - - Tomasz Kusy - - Johannes Klauss (cloppy) - Evan Villemez + - Alexander Miehe + - Morgan Auchede - fzerorubigd - - Thomas Ploch - - Benjamin Grandfond (benjamin) - Tiago Brito (blackmx) - Gintautas Miselis (naktibalda) - Richard van den Brand (ricbra) - - Toon Verwerft (veewee) - develop - - flip111 - - Douglas Hammond (wizhippo) - - VJ - - RJ Garcia - Adrien Lucas (adrienlucas) - - Jawira Portugal (jawira) - - Delf Tonder (leberknecht) - - Ondrej Exner - Mark Sonnabaum - Chris Jones (magikid) - Massimiliano Braglia (massimilianobraglia) - - Thijs-jan Veldhuizen (tjveldhuizen) + - Alexandre parent + - Jakub Podhorsky (podhy) + - Jean-Baptiste GOMOND (mjbgo) + - Dmytro Boiko (eagle) + - Daniël Brekelmans (dbrekelmans) + - Andreas Leathley (iquito) - Richard Quadling - James Hudson (mrthehud) + - Roland Franssen :) - Raphaëll Roussel + - Simon Heimberg (simon_heimberg) + - Sergey Zolotov (enleur) + - Benoît Bourgeois (bierdok) - Michael Lutz - jochenvdv + - Andrew Codispoti + - mweimerskirch + - Sebastian Grodzicki (sgrodzicki) + - Jan Kramer - Oriol Viñals + - Jay Klehr - Reedy + - Simo Heinonen (simoheinonen) - Arturas Smorgun (asarturas) - Aleksandr Volochnev (exelenz) - - Robin van der Vleuten (robinvdvleuten) + - grizlik + - Thijs-jan Veldhuizen (tjveldhuizen) + - wanxiangchwng - Grinbergs Reinis (shima5) + - Vladimir Luchaninov (luchaninov) + - NanoSector + - bogdan - Michael Piecko (michael.piecko) + - Julien DIDIER (juliendidier) - Toni Peric (tperic) - - yclian - - Nicolas DOUSSON + - Wybren Koelmans (wybren_koelmans) + - Davide Borsatto (davide.borsatto) - radar3301 - - Aleksey Prilipko - Jelle Raaijmakers (gmta) - - Andrew Berry - - Sylvain BEISSIER (sylvain-beissier) - - Wybren Koelmans (wybren_koelmans) - Roberto Nygaard - - victor-prdh - - Davide Borsatto (davide.borsatto) - - Florian Hermann (fhermann) - Vitaliy Zhuk (zhukv) + - mwsaz - zenas1210 - Gert de Pagter - - Julien DIDIER (juliendidier) + - Jason Woods + - Andrii Popov (andrii-popov) - Ворожцов Максим (myks92) - Randy Geraads - Kevin van Sonsbeek (kevin_van_sonsbeek) - - Simo Heinonen (simoheinonen) - - Jay Klehr - - Andreas Leathley (iquito) - - Vladimir Luchaninov (luchaninov) - - Sebastian Grodzicki (sgrodzicki) - Mohamed Gamal - Eric COURTIAL - Xesxen - - Jeroen van den Enden (endroid) - Arun Philip + - flip111 + - Baldur Rensch (brensch) - Pascal Helfenstein - Jesper Skytte (greew) - - NanoSector + - Stéphan Kochen - Petar Obradović - - Baldur Rensch (brensch) - - Carl Casbolt (carlcasbolt) + - Konstantin Grachev (grachevko) + - Alex (garrett) + - yclian + - David Marín Carreño (davefx) + - Tarjei Huse (tarjei) + - Paweł Niedzielski (steveb) + - stoccc - Jiri Barous + - Simon Mönch - Vladyslav Petrovych + - Robert Fischer (sandoba) + - Jörn Lang + - Amr Ezzat (amrezzat) + - Maksim Kotlyar (makasim) + - arai + - Carl Casbolt (carlcasbolt) + - Simon (kosssi) + - Derek ROTH + - Benjamin Laugueux + - Jose Gonzalez + - Moshe Weitzman (weitzman) - Loïc Chardonnet - - Alex Xandra Albert Sim - - Sergey Yastrebov - Carson Full (carsonfull) - - Steve Grunwell - - Yuen-Chi Lian + - Sergey Yastrebov + - Alex Xandra Albert Sim - Mathias Brodala (mbrodala) - - Robert Fischer (sandoba) - - Tarjei Huse (tarjei) - Travis Carden (traviscarden) - - mfettig - Besnik Br - - Simon Mönch - - Valmonzo - Sherin Bloemendaal - - Jose Gonzalez - Jonathan (jlslew) - Claudio Zizza - aegypius - Ilia (aliance) - - Christian Stoller (naitsirch) - COMBROUSE Dimitri - Dave Marshall (davedevelopment) - Jakub Kulhan (jakubkulhan) - - Paweł Niedzielski (steveb) - Shaharia Azam - avorobiev - Gerben Oolbekkink - Gladhon - Maximilian.Beckers + - skmedix (skmedix) + - Shin Ohno (ganchiku) + - Gabrielle Langer + - Lctrs - Alex Kalineskou + - Calin Mihai Pristavu - Evan Shaw - - stoccc - Grégoire Penverne (gpenverne) - Venu - Ryan Hendrickson - Damien Fa - Jonatan Männchen + - Carlos Buenosvinos (carlosbuenosvinos) - Dennis Hotson - - Andrew Tchircoff (andrewtch) - Lars Vierbergen (vierbergenlars) + - Sander De la Marche (sanderdlm) + - Gálik Pál + - Marco Lipparini (liarco) + - Korvin Szanto - Xav` (xavismeh) - Barney Hanlon + - Adrian Günter (adrianguenter) + - Jordan Deitch - Thorry84 - Romanavr - - michaelwilliams - - Alexandre Parent - - 1emming + - Seb Koelen + - Hidde Boomsma (hboomsma) - Eric Abouaf (neyric) - - Nykopol (nykopol) - - Thibault Richard (t-richard) - - Jordan Deitch - - Casper Valdemar Poulsen + - Daniel González (daniel.gonzalez) + - Ondrej Machulda (ondram) + - Alexander Grimalovsky (flying) + - Yosmany Garcia (yosmanyga) + - Thomas Durand - Guillaume Verstraete - - vladimir.panivko + - izzyp + - Fabien LUCAS (flucas2) + - Jon Dufresne - Oliver Hader + - Gustavo Falco (gfalco) - Josiah (josiah) + - Thomas Trautner (thomastr) - Dennis Væversted (srnzitcom) + - Jason Tan (jt2k) - AndrolGenhald + - Thibault Richard (t-richard) - Asier Etxebeste - - Joschi Kuphal - - John Bohn (jbohn) - - Jason Tan (jt2k) + - Matt Robinson (inanimatt) + - Alexander Li (aweelex) - Edvin Hultberg - shubhalgupta - Felds Liscia (felds) - Benjamin Lebon - - Alexander Grimalovsky (flying) - Andrew Hilobok (hilobok) - Noah Heck (myesain) - - Sébastien JEAN (sebastien76) + - Benoît Merlet (trompette) - Christian Soronellas (theunic) - - Max Baldanza - Volodymyr Panivko + - Patrick Allaert + - Kristof Van Cauwenbergh (kristofvc) - kick-the-bucket - - Thomas Durand - fedor.f - - Yosmany Garcia (yosmanyga) - Jeremiasz Major - - Jibé Barth (jibbarth) - Trevor North - Degory Valentine - - izzyp + - Laurent Bassin (lbassin) - Jeroen Fiege (fieg) - Martin (meckhardt) - Wu (wu-agriconomie) - Marcel Hernandez - Evan C + - Geert De Deckere - buffcode + - abdul malik ikhsan (samsonasik) - Glodzienski - - Natsuki Ikeguchi + - Ivan Menshykov + - Sinan Eldem (sineld) - Krzysztof Łabuś (crozin) - Xavier Lacot (xavier) - - Jon Dufresne - - possum + - Maxim Tugaev (tugmaks) - Denis Zunke (donalberto) - Adrien Roches (neirda24) - - Thomas Trautner (thomastr) - - _sir_kane (waly) + - Nicolas Dousson - Olivier Maisonneuve - - Gálik Pál + - Christian Stoller (naitsirch) - Bálint Szekeres - Andrei C. (moldman) - Mike Meier (mykon) - - Pedro Miguel Maymone de Resende (pedroresende) + - Vincent Composieux (eko) + - VJ + - Jordi Sala Morales (jsala) + - Tamas Szijarto - stlrnz - - Masterklavi + - Quentin Dreyer (qkdreyer) + - Vincent CHALAMON + - Sébastien JEAN (sebastien76) - Adrien Wilmet (adrienfr) + - Pedro Miguel Maymone de Resende (pedroresende) + - Johnny Peck (johnnypeck) + - Gerard van Helden (drm) + - Cyril Quintin (cyqui) - Franco Traversaro (belinde) + - Tomasz Ignatiuk - Francis Turmel (fturmel) - Kagan Balga (kagan-balga) - Nikita Nefedov (nikita2206) - Alex Bacart - StefanoTarditi - - cgonzalez - - hugovms - - Ben - - Vincent Composieux (eko) + - ampaze - Cyril Pascal (paxal) - Pedro Casado (pdr33n) - - Jayson Xu (superjavason) - acoulton + - Guilherme Augusto Henschel + - Tomasz Kusy - DemigodCode - fago - Jan Prieser + - Johannes Klauss (cloppy) - Maximilian Bösing - Matt Johnson (gdibass) - Zhuravlev Alexander (scif) - Stefano Degenkamp (steef) - James Michael DuPont - Tinjo Schöni - - Carlos Buenosvinos (carlosbuenosvinos) - Jake (jakesoft) - Rustam Bakeev (nommyde) - - Vincent CHALAMON - Ivan Kurnosov + - DUPUCH (bdupuch) - Christopher Hall (mythmakr) - Patrick Dawkins (pjcdawkins) + - Artur Eshenbrener + - Florian Wolfsjaeger (flowolf) - Paul Kamer (pkamer) + - MrMicky - Rafał Wrzeszcz (rafalwrzeszcz) - Reyo Stallenberg (reyostallenberg) + - Thibault Buathier (gwemox) - Nguyen Xuan Quynh - - Reen Lokum - Dennis Langen (nijusan) - - Quentin Dreyer (qkdreyer) + - Andreas Lutro (anlutro) + - Christin Gruber (christingruber) - Francisco Alvarez (sormes) - Martin Parsiegla (spea) - - Maxim Tugaev (tugmaks) - - ywisax - Manuel Alejandro Paz Cetina + - Rootie - Denis Charrier (brucewouaigne) + - Roy Klutman (royklutman) + - Nicole Cordes (ichhabrecht) + - Matthieu Calie (matth--) + - Ulumuddin Cahyadi Yunus (joenoez) + - alexpozzi + - NickSdot - Youssef Benhssaien (moghreb) - Mario Ramundo (rammar) - - Ivan - - Nico Haase - - Philipp Scheit (pscheit) - - Pierre Vanliefland (pvanliefland) - - Roy Klutman (royklutman) + - David Romaní - Sofiane HADDAG (sofhad) - - Antoine M - - frost-nzcr4 - - Shahriar56 - - Dhananjay Goratela - - Kien Nguyen - - Bozhidar Hristov - - Oriol Viñals - - arai - - Achilles Kaloeridis (achilles) - - Sébastien Despont (bouillou) - - Laurent Bassin (lbassin) - - Mouad ZIANI (mouadziani) - - Tomasz Ignatiuk - - andrey1s - - Abhoryo - - louismariegaborit - - Fabian Vogler (fabian) - - Korvin Szanto - - Stéphan Kochen - - Arjan Keeman - - Alaattin Kahramanlar (alaattin) - - Sergey Zolotov (enleur) - - Nicole Cordes (ichhabrecht) - - Maksim Kotlyar (makasim) - - Thibaut THOUEMENT (thibaut_thouement) - - Neil Ferreira - - Julie Hourcade (juliehde) - - Dmitry Parnas (parnas) - - Loïc Beurlet - - Ana Raro - - Ana Raro + - Casper Valdemar Poulsen + - Andrew Berry - Tony Malzhacker - - Cosmin Sandu - - Andreas Lutro (anlutro) - - DUPUCH (bdupuch) - - Cyril Quintin (cyqui) - - Gerard van Helden (drm) - - Florent Destremau (florentdestremau) - - Florian Wolfsjaeger (flowolf) - - Johnny Peck (johnnypeck) - - Jordi Sala Morales (jsala) - - Sander De la Marche (sanderdlm) - - skmedix (skmedix) - - Loic Chardonnet - - Ivan Menshykov - - David Romaní - - Patrick Allaert - - Alexander Li (aweelex) - - Gustavo Falco (gfalco) - - Matt Robinson (inanimatt) - - Kristof Van Cauwenbergh (kristofvc) - - Marco Lipparini (liarco) - - Aleksey Podskrebyshev - - Calin Mihai Pristavu - - Gabrielle Langer - - Jörn Lang - - Adrian Günter (adrianguenter) - - Amr Ezzat (amrezzat) - - David Marín Carreño (davefx) - - Fabien LUCAS (flucas2) - - Alex (garrett) - - Konstantin Grachev (grachevko) - - Hidde Boomsma (hboomsma) - - Ondrej Machulda (ondram) - - Jason Woods - - mwsaz - - bogdan - - wanxiangchwng - - Geert De Deckere - - grizlik - - Derek ROTH - - Jeremy Benoist - - Ben Johnson - - Jan Kramer - - mweimerskirch - - Andrew Codispoti - - Benjamin Laugueux - - Lctrs - - Benoît Bourgeois (bierdok) - - Dmytro Boiko (eagle) - - Shin Ohno (ganchiku) + - Loïc Beurlet + - mfettig + - John Bohn (jbohn) + - hugovms + - Ben + - Andrew Tchircoff (andrewtch) + - Natsuki Ikeguchi + - Jesper Noordsij + - Adán Lobato (adanlobato) + - Neil Ferreira - Matthieu Mota (matthieumota) - - Jean-Baptiste GOMOND (mjbgo) - - Jakub Podhorsky (podhy) - - abdul malik ikhsan (samsonasik) - - Henry Snoek (snoek09) - - Morgan Auchede - - Christian Morgan - - Alexander Miehe - - Daniël Brekelmans (dbrekelmans) - - Simon (kosssi) - - Sascha Dens (saschadens) - - Simon Heimberg (simon_heimberg) - - Morten Wulff (wulff) - - Kieran - - Don Pinkster - Maksim Muruev - - Emil Einarsson - - 243083df - - Thibault Duplessis - - katario - - Rimas Kudelis - - Marc Abramowitz - - Matthias Schmidt - - Martijn Evers - - Tony Tran - - Balazs Csaba - - Bill Hance (billhance) - - Douglas Reith (douglas_reith) - - Harry Walter (haswalt) - - Jacques MOATI (jmoati) - - Johnson Page (jwpage) - - Kuba Werłos (kuba) - - Ruben Gonzalez (rubenruateltek) - - Michael Roterman (wtfzdotnet) - - Philipp Keck - - Pavol Tuka - - Arno Geurts - - Adán Lobato (adanlobato) + - datibbaw + - Daniel Alejandro Castro Arellano (lexcast) + - Ondrej Exner + - Masterklavi + - vladimir.panivko + - Sébastien Santoro (dereckson) + - Ian Irlen + - Marko Petrovic + - Matthieu Bontemps + - Stephan Vierkant (svierkant) + - Thiago Cordeiro (thiagocordeiro) + - Ana Raro + - Koen Kuipers (koku) + - Ana Raro + - Dragos Protung (dragosprotung) + - Carlos Quintana + - Mouad ZIANI (mouadziani) + - Jibé Barth (jibbarth) + - Dmitry Parnas (parnas) + - Brad Jones - Ian Jenkins (jenkoian) - - Marcos Gómez Vilches (markitosgv) - - Matthew Davis (mdavis1982) - - Paulo Ribeiro (paulo) - - Marc Laporte - - Michał Jusięga - - Kay Wei - - Dominik Ulrich - - den - - Gábor Tóth - - Bastien THOMAS - - ouardisoft - - Daniel Cestari - - Matt Janssen - - Stéphane Delprat - - Mior Muhammad Zaki (crynobone) - - Elan Ruusamäe (glen) - - Brunet Laurent (lbrunet) - - Florent Viel (luxifer) - - Maks 3w (maks3w) - - Michiel Boeckaert (milio) - - Mikhail Yurasov (mym) - Robert Gruendler (pulse00) - - Sebastian Paczkowski (sebpacz) - Simon Terrien (sterrien) - - Stephan Vierkant (svierkant) - - Benoît Merlet (trompette) - - Brad Jones - - datibbaw - - Dragos Protung (dragosprotung) - - Koen Kuipers (koku) + - Sebastian Paczkowski (sebpacz) - Nicolas de Marqué (nicola) - - Thiago Cordeiro (thiagocordeiro) - - Matthieu Bontemps - - Ian Irlen - - Rootie - - Sébastien Santoro (dereckson) - - Daniel Alejandro Castro Arellano (lexcast) - - Jiří Bok - - Vincent Chalamon - - Farhad Hedayatifard - - Alan ZARLI - - Thomas Jarrand - - Baptiste Leduc (bleduc) - - soyuka - - Piotr Zajac - - Patrick Kaufmann - - Ismail Özgün Turan (dadeather) - - Mickael Perraud - - Anton Dyshkant - - Rafael Villa Verde - - Zoran Makrevski (zmakrevski) - - Yann LUCAS (drixs6o9) - - Kirill Nesmeyanov (serafim) - - Reece Fowell (reecefowell) - - Muhammad Aakash - - Charly Goblet (_mocodo) - - Htun Htun Htet (ryanhhh91) - - Guillaume Gammelin - - Valérian Galliat - - Sorin Pop (sorinpop) - - Elías Fernández - - d-ph - - Stewart Malik - - Frank Schulze (xit) - - Renan Taranto (renan-taranto) - - Ninos Ego - - Samael tomas - - Stefan Graupner (efrane) - - Gemorroj (gemorroj) - - Adrien Chinour - - Jonas Claes - - Mateusz Żyła (plotkabytes) - - Rikijs Murgs - - WoutervanderLoop.nl - - Mihail Krasilnikov (krasilnikovm) - - Uladzimir Tsykun - - iamvar - - Amaury Leroux de Lens (amo__) - - Rene de Lima Barbosa (renedelima) - - Christian Jul Jensen - - Lukas Kaltenbach - - Alexandre GESLIN - - The Whole Life to Learn - - Pierre Tondereau - - Joel Lusavuvu (enigma97) - - Valentin Barbu (jimie) - - Alex Vo (votanlean) - - Mikkel Paulson - - ergiegonzaga - - André Matthies - - kurozumi (kurozumi) - - Nicolas Lemoine - - Piergiuseppe Longo - - Kevin Auivinet - - Liverbool (liverbool) - - Valentin Nazarov - - Dalibor Karlović - - Aurélien MARTIN - - Malte Schlüter - - Jules Matsounga (hyoa) - - Yewhen Khoptynskyi (khoptynskyi) - - Nicolas Attard (nicolasattard) - - Jérôme Nadaud (jnadaud) - - Frank Naegler - - Sam Malone - - Damien Fernandes - - Ha Phan (haphan) - - Chris Jones (leek) - - neghmurken - - stefan.r - - Florian Cellier - - xaav - - Jean-Christophe Cuvelier [Artack] - - Mahmoud Mostafa (mahmoud) - - Alexandre Tranchant (alexandre_t) - - Anthony Moutte - - Ahmed Abdou - - shreyadenny - - Daniel Iwaniec - - Thomas Ferney (thomasf) - - Pieter - - Louis-Proffit - - Dennis Tobar - - Michael Tibben - - Hallison Boaventura (hallisonboaventura) - - Mas Iting - - Billie Thompson - - Albion Bame (abame) - - Ganesh Chandrasekaran (gxc4795) - - Sander Marechal - - Ivan Nemets - - Grégoire Hébert (gregoirehebert) - - Franz Wilding (killerpoke) - - Ferenczi Krisztian (fchris82) - - Artyum Petrov - - Oleg Golovakhin (doc_tr) - - Guillaume Smolders (guillaumesmo) - - Icode4Food (icode4food) - - Radosław Benkel - - Bert ter Heide (bertterheide) - - Kevin Nadin (kevinjhappy) - - jean pasqualini (darkilliant) - - Iliya Miroslavov Iliev (i.miroslavov) - - Safonov Nikita (ns3777k) - - Ross Motley (rossmotley) - - ttomor - - Mei Gwilym (meigwilym) - - Michael H. Arieli - - Miloš Milutinović - - Jitendra Adhikari (adhocore) - - Kevin Jansen - - Nicolas Martin (cocorambo) - - Tom Panier (neemzy) + - Mikhail Yurasov (mym) + - Fabian Vogler (fabian) + - Brunet Laurent (lbrunet) + - Elan Ruusamäe (glen) + - Mior Muhammad Zaki (crynobone) + - Julie Hourcade (juliehde) + - Henry Snoek (snoek09) + - Wouter van der Loop (toppy-hennie) + - Adam + - johan Vlaar + - Ivan + - Jeroen van den Enden (endroid) + - Mantas Var (mvar) + - Pierre Vanliefland (pvanliefland) + - Nico Haase + - frost-nzcr4 + - wuchen90 + - Philipp Scheit (pscheit) + - SpacePossum + - Arjan Keeman + - Arnaud Frézet + - Terje Bråten + - Sylvain BEISSIER (sylvain-beissier) + - Bozhidar Hristov + - Thibaut THOUEMENT (thibaut_thouement) + - Cosmin Sandu + - wicliff wolda (wickedone) + - Florent Destremau (florentdestremau) + - Stéphane Delprat + - Andreas Braun + - James Hemery + - Michiel Boeckaert (milio) + - Bastien DURAND (deamon) + - Daniel Cestari + - Mátyás Somfai (smatyas) + - ouardisoft + - Sebastian Krebs + - Mickaël Andrieu (mickaelandrieu) + - Daisuke Ohata + - Simon Leblanc (leblanc_simon) + - Paul Oms + - Egor Taranov + - Piotr Stankowski + - Bastien THOMAS + - Gábor Tóth + - Yuriy Vilks (igrizzli) + - Ramunas Pabreza (doobas) + - Achilles Kaloeridis (achilles) + - den + - Pierre-Emmanuel Tanguy (petanguy) + - Julien Maulny + - Gennadi Janzen + - Shahriar56 + - julien57 - Fred Cox - - luffy1727 - - Luciano Mammino (loige) - - LHommet Nicolas (nicolaslh) - - fabios - - eRIZ - - Sander Coolen (scoolen) - - Vic D'Elfant (vicdelfant) - - Amirreza Shafaat (amirrezashafaat) - - Laurent Clouet - - Adoni Pavlakis (adoni) - - Nicolas Le Goff (nlegoff) - - Maarten Nusteling (nusje2000) - - Peter van Dommelen - - Anne-Sophie Bachelard - - Gordienko Vladislav - - Ahmed EBEN HASSINE (famas23) - - Marvin Butkereit - - Ben Oman - - Chris de Kok - - Eduard Bulava (nonanerz) - - Andreas Kleemann (andesk) - - Hubert Moreau (hmoreau) - - Nicolas Appriou - - Silas Joisten (silasjoisten) - - Igor Timoshenko (igor.timoshenko) - - Pierre-Emmanuel CAPEL - - Manuele Menozzi - - Yevhen Sidelnyk - - “teerasak” - - Anton Babenko (antonbabenko) - - Irmantas Šiupšinskas (irmantas) - - Benoit Mallo - - Charles-Henri Bruyand - - Danilo Silva - - Giuseppe Campanelli - - Valentin - - pizzaminded - - Nicolas Valverde - - Konstantin S. M. Möllers (ksmmoellers) - - Ken Stanley - - ivan - - Zachary Tong (polyfractal) - - linh - - Oleg Krasavin (okwinza) - - Mario Blažek (marioblazek) - - Jure (zamzung) - - Michael Nelson - - Ashura - - Hryhorii Hrebiniuk - - Nsbx - - Eric Krona - - Alex Plekhanov - - johnstevenson - - hamza - - dantleech - - Kajetan Kołtuniak (kajtii) - - Dan (dantleech) - - Sander Goossens (sandergo90) - - Rudy Onfroy - - Tero Alén (tero) - - DerManoMann - - Damien Fayet (rainst0rm) - - MatTheCat - - Guillaume Royer - - Erfan Bahramali - - Artem (digi) - - boite - - Silvio Ginter - - Peter Culka - - MGDSoft - - Abdiel Carrazana (abdielcs) - - joris - - Vadim Tyukov (vatson) - - alanzarli - - Arman - - Gabi Udrescu - - Adamo Crespi (aerendir) - - David Wolter (davewww) - - Sortex - - chispita - - Wojciech Sznapka - - Emmanuel Dreyfus - - Luis Pabon (luispabon) - - boulei_n - - Anna Filina (afilina) - - Gavin (gavin-markup) - - Ksaveras Šakys (xawiers) - - Shaun Simmons - - Ariel J. Birnbaum - - Yannick - - Patrick Luca Fazzi (ap3ir0n) - - Tim Lieberman - - Danijel Obradović - - Pablo Borowicz - - Ondřej Frei - - Bruno Rodrigues de Araujo (brunosinister) - - Máximo Cuadros (mcuadros) - - Arkalo2 - - Jacek Wilczyński (jacekwilczynski) - - Christoph Kappestein - - Camille Baronnet - - EXT - THERAGE Kevin - - tamirvs - - gauss - - julien.galenski - - Florian Guimier - - Maxime PINEAU - - Igor Kokhlov (verdet) - - Christian Neff (secondtruth) - - Chris Tiearney - - Oliver Hoff - - Minna N - - Ole Rößner (basster) - - andersmateusz - - Laurent Moreau - - Faton (notaf) - - Tom Houdmont - - tamar peled - - mark burdett - - Per Sandström (per) - - Goran Juric - - Laurent G. (laurentg) - - Jean-Baptiste Nahan - - Thomas Decaux - - Nicolas Macherey - - Asil Barkin Elik (asilelik) - - Bhujagendra Ishaya - - Guido Donnari - - Jérôme Dumas - - Mert Simsek (mrtsmsk0) - - Lin Clark - - Christophe Meneses (c77men) - - Jeremy David (jeremy.david) - - Andrei O - - gr8b - - Michał Marcin Brzuchalski (brzuchal) - - Jordi Rejas - - Troy McCabe - - Ville Mattila - - gstapinato - - gr1ev0us - - Léo VINCENT - - mlazovla - - Alejandro Diaz Torres - - Bradley Zeggelaar - - Karl Shea - - Valentin - - Markus Baumer - - Max Beutel - - adnen chouibi - - Nathan Sepulveda - - Łukasz Chruściel (lchrusciel) - - Jan Vernieuwe (vernija) - - Antanas Arvasevicius - - Adam Kiss - - Pierre Dudoret - - Michal Trojanowski - - Thomas - - j.schmitt - - Georgi Georgiev - - Norbert Schultheisz - - Maximilian Berghoff (electricmaxxx) - - SOEDJEDE Felix (fsoedjede) - - Evgeny Anisiforov - - otsch - - TristanPouliquen - - Dominic Luidold - - Piotr Antosik (antek88) - - Nacho Martin (nacmartin) - - Thomas Bibaut - - Thibaut Chieux - - mwos - - Aydin Hassan - - Volker Killesreiter (ol0lll) - - Vedran Mihočinec (v-m-i) - - Rafał Treffler - - Sergey Novikov (s12v) - - creiner - - Jan Pintr - - ProgMiner - - Marcos Quesada (marcos_quesada) - - Matthew (mattvick) - - MARYNICH Mikhail (mmarynich-ext) - - Viktor Novikov (nowiko) - - Paul Mitchum (paul-m) - - Angel Koilov (po_taka) - - RevZer0 (rav) - - Yura Uvarov (zim32) - - Dan Finnie - - remieuronews - - Marek Binkowski - - Ken Marfilla (marfillaster) - - Max Grigorian (maxakawizard) - - allison guilhem - - benatespina (benatespina) - - Denis Kop - - Fabrice Locher - - Konstantin Chigakov - - Kamil Szalewski (szal1k) - - Jean-Guilhem Rouel (jean-gui) - - Yoann MOROCUTTI - - Ivan Yivoff - - EdgarPE - - jfcixmedia - - Dominic Tubach - - Martijn Evers - - Alexander Onatskiy - - Philipp Fritsche - - Léon Gersen - - tarlepp - - Giuseppe Arcuti - - Dustin Wilson - - Benjamin Paap (benjaminpaap) - - Claus Due (namelesscoder) - - Christian - - Alexandru Patranescu - - Sébastien Lévêque (legenyes) - - ju1ius - - Denis Golubovskiy (bukashk0zzz) - - Arkadiusz Rzadkowolski (flies) - - Serge (nfx) - - Oksana Kozlova (oksanakozlova) - - Quentin Moreau (sheitak) - - Mikkel Paulson - - Michał Strzelecki - - Bert Ramakers - - Hugo Fonseca (fonsecas72) - - Marc Duboc (icemad) - - uncaught - - Martynas Narbutas - - Timothée BARRAY - - Nilmar Sanchez Muguercia - - Pierre LEJEUNE (darkanakin41) - - Bailey Parker - - curlycarla2004 - - Javier Ledezma - - Kevin Auvinet - - Antanas Arvasevicius - - Kris Kelly - - Eddie Abou-Jaoude (eddiejaoude) - - Haritz Iturbe (hizai) - - Nerijus Arlauskas (nercury) - - Stanislau Kviatkouski (7-zete-7) - - Rutger Hertogh - - Diego Sapriza - - Joan Cruz - - inspiran - - Alex Demchenko - - Richard van Velzen - - Cristobal Dabed - - Daniel Mecke (daniel_mecke) - - Matteo Giachino (matteosister) - - Serhii Polishchuk (spolischook) - - Tadas Gliaubicas (tadcka) - - Thanos Polymeneas (thanos) - - Atthaphon Urairat - - Benoit Garret - - HellFirePvP - - Maximilian Ruta (deltachaos) - - Jon Green (jontjs) - - Jakub Sacha - - Julius Kiekbusch - - Kamil Musial - - Lucas Bustamante - - Olaf Klischat - - Andrii - - orlovv - - Claude Dioudonnat - - Jonathan Hedstrom - - Peter Smeets (darkspartan) - - Julien Bianchi (jubianchi) - - Michael Dawart (mdawart) - - Robert Meijers - - Tijs Verkoyen - - James Sansbury - - Marcin Chwedziak - - Dan Kadera - - hjkl - - Dan Wilga - - Thijs Reijgersberg - - Florian Heller - - Oleksii Svitiashchuk - - Andrew Tch - - Alexander Cheprasov - - Tristan Bessoussa (sf_tristanb) - - Rodrigo Díez Villamuera (rodrigodiez) - - Brad Treloar - - pritasil - - Stephen Clouse - - e-ivanov - - Nathanaël Martel (nathanaelmartel) - - Nicolas Jourdan (nicolasjc) - - Benjamin Dos Santos - - Abderrahman DAIF (death_maker) - - Yann Rabiller (einenlum) - - GagnarTest (gagnartest) - - Jochen Bayer (jocl) - - Tomas Javaisis - - Constantine Shtompel - - VAN DER PUTTE Guillaume (guillaume_vdp) - - Patrick Carlo-Hickman - - Bruno MATEU - - Jeremy Bush - - Lucas Bäuerle - - Laurens Laman - - Thomason, James - - Dario Savella - - Gordienko Vladislav - - Joas Schilling - - Ener-Getick - - Markus Thielen - - Peter Trebaticky - - Moza Bogdan (bogdan_moza) - - Viacheslav Sychov - - Zuruuh - - Nicolas Sauveur (baishu) - - Helmut Hummel (helhum) - - Matt Brunt - - David Vancl - - Carlos Ortega Huetos - - Péter Buri (burci) - - Evgeny Efimov (edefimov) - - jack.thomas (jackthomasatl) - - John VanDeWeghe - - kaiwa - - Charles Sanquer (csanquer) - - Albert Ganiev (helios-ag) - - Neil Katin - - Oleg Mifle - - V1nicius00 - - David Otton - - Will Donohoe - - peter - - Tugba Celebioglu - - Jeroen de Boer - - Oleg Sedinkin (akeylimepie) - - Jérémy Jourdin (jjk801) - - BRAMILLE Sébastien (oktapodia) - - Artem Kolesnikov (tyomo4ka) - - Markkus Millend - - Clément - - Gustavo Adrian - - Jorrit Schippers (jorrit) - - Yann (yann_eugone) - - Matthias Neid - - danilovict2 - - Yannick - - Kuzia - - spdionis - - maxime.perrimond - - rchoquet - - v.shevelev - - rvoisin - - Dan Brown - - gitlost - - Taras Girnyk - - Simon Mönch - - Barthold Bos - - cthulhu - - Andoni Larzabal (andonilarz) - - Wolfgang Klinger (wolfgangklingerplan2net) - - Staormin - - Dmitry Derepko - - Rémi Leclerc - - Jan Vernarsky - - Ionut Cioflan - - John Edmerson Pizarra - - Sergio - - Jonas Hünig - - Mehrdad - - Amine Yakoubi - - Eduardo García Sanz (coma) - - Arend Hummeling - - Makdessi Alex - - Dmitrii Baranov - - fduch (fduch) - - Juan Miguel Besada Vidal (soutlink) - - Takashi Kanemoto (ttskch) - - Aleksei Lebedev - - dlorek - - Stuart Fyfe - - Jason Schilling (chapterjason) - - David de Boer (ddeboer) - - Eno Mullaraj (emullaraj) - - Guillem Fondin (guillemfondin) - - Nathan PAGE (nathix) - - Ryan Rogers - - Arnaud - - Klaus Purer - - Dmitrii Lozhkin - - Gilles Doge (gido) - - Marion Hurteau (marionleherisson) - - Oscar Esteve (oesteve) - - Sobhan Sharifi (50bhan) - - Peter Potrowl - - abulford - - Philipp Kretzschmar - - Jairo Pastor - - Ilya Vertakov - - Brooks Boyd - - Axel Venet - - Stephen - - Roger Webb - - Dmitriy Simushev - - Pawel Smolinski - - Yury (daffox) - - John Espiritu (johnillo) - - Tomasz (timitao) - - Nguyen Tuan Minh (tuanminhgp) - - Oxan van Leeuwen - - pkowalczyk - - dbrekelmans - - Mykola Zyk - - Soner Sayakci - - Max Voloshin (maxvoloshin) - - Nicolas Fabre (nfabre) - - Raul Rodriguez (raul782) - - Piet Steinhart - - mousezheng - - Radoslaw Kowalewski - - mshavliuk - - Rémy LESCALLIER - - MightyBranch - - Kacper Gunia (cakper) - - Derek Lambert (dlambert) - - Mark Pedron (markpedron) - - Peter Thompson (petert82) - - Victor Macko (victor_m) - - Ismail Turan - - error56 - - Felicitus - - Jorge Vahldick (jvahldick) - - Krzysztof Przybyszewski (kprzybyszewski) - - Vladimir Mantulo (mantulo) - - Boullé William (williamboulle) - - Jesper Noordsij - - Bart Baaten - - Frederic Godfrin - - Paul Matthews - - aim8604 - - Jakub Kisielewski - - Vacheslav Silyutin - - Aleksandr Dankovtsev - - Maciej Zgadzaj - - Juan Traverso - - David Legatt (dlegatt) - - Alain Flaus (halundra) - - Arthur Woimbée - - tsufeki - - Théo DELCEY - - Philipp Strube - - Wim Hendrikx - - Andrii Serdiuk (andreyserdjuk) - - Clement Herreman (clemherreman) - - dangkhoagms (dangkhoagms) - - Dan Ionut Dumitriu (danionut90) - - Evgeny (disparity) - - Floran Brutel (notFloran) (floran) - - Vladislav Rastrusny (fractalizer) - - Vlad Gapanovich (gapik) - - Alexander Kurilo (kamazee) - - nyro (nyro) - - Konstantin Bogomolov - - Marco - - Marc Torres - - Mark Spink - - gndk - - Alberto Aldegheri - - Dalibor Karlović - - Cesar Scur (cesarscur) - - Cyril Vermandé (cyve) - - Daniele Orru' (danydev) - - Raul Garcia Canet (juagarc4) - - Sagrario Meneses - - Dmitri Petmanson - - heccjj - - Alexandre Melard - - Rafał Toboła - - Dominik Schwind (dominikschwind) - - Stefano A. (stefano93) - - PierreRebeilleau - - AlbinoDrought - - Sergey Yuferev - - Monet Emilien - - voodooism - - Tobias Stöckler - - Mario Young - - martkop26 - - Raphaël Davaillaud - - Sander Hagen - - Alexander Menk - - cilefen (cilefen) - - Prasetyo Wicaksono (jowy) - - Mo Di (modi) - - Victor Truhanovich (victor_truhanovich) - - Pablo Schläpfer - - Christian Rishøj - - Nikos Charalampidis - - Caligone - - Roromix - - Patrick Berenschot - - SuRiKmAn - - Xavier RENAUDIN - - rtek - - Christian Wahler (christian) - - Jelte Steijaert (jelte) - - Maxime AILLOUD (mailloud) - - David Négrier (moufmouf) - - Quique Porta (quiqueporta) - - Tobias Feijten (tobias93) - - mohammadreza honarkhah - - Jessica F Martinez - - paullallier - - Artem Oliinyk (artemoliynyk) - - Andrea Quintino (dirk39) - - Andreas Heigl (heiglandreas) - - Tomasz Szymczyk (karion) - - Peter Dietrich (xosofox) - - Alex Vasilchenko - - sez-open - - fruty - - ConneXNL - - Aharon Perkel - - matze - - Adam Wójs (awojs) - - Justin Reherman (jreherman) - - Rubén Calvo (rubencm) - - Abdul.Mohsen B. A. A - - Cédric Girard - - Peter Jaap Blaakmeer - - Robert Worgul - - Swen van Zanten - - Agustin Gomes - - pthompson - - Malaney J. Hill - - Patryk Kozłowski - - Alexandre Pavy - - Tim Ward - - Adiel Cristo (arcristo) - - Christian Flach (cmfcmf) - - Dennis Jaschinski (d.jaschinski) - - Fabian Kropfhamer (fabiank) - - Jeffrey Cafferata (jcidnl) - - Junaid Farooq (junaidfarooq) - - Lars Ambrosius Wallenborn (larsborn) - - Pavel Starosek (octisher) - - Oriol Mangas Abellan (oriolman) - - Sebastian Göttschkes (sgoettschkes) - - Marcin Nowak - - Frankie Wittevrongel - - Tatsuya Tsuruoka - - Ross Tuck - - omniError - - Zander Baldwin - - László GÖRÖG - - djordy - - Kévin Gomez (kevin) - - Mihai Nica (redecs) - - Andrei Igna - - Adam Prickett - - azine - - Luke Towers - - Wojciech Zimoń - - Vladimir Melnik - - Anton Kroshilin - - Pierre Tachoire - - Dawid Sajdak - - Maxime THIRY - - Norman Soetbeer - - Ludek Stepan - - Benjamin BOUDIER - - Frederik Schwan - - Mark van den Berg - - Aaron Stephens (astephens) - - Craig Menning (cmenning) - - Balázs Benyó (duplabe) - - Erika Heidi Reinaldo (erikaheidi) - - William Thomson (gauss) - - Javier Espinosa (javespi) - - Marc J. Schmidt (marcjs) - - František Maša - - Sebastian Schwarz - - Flohw - - karolsojko - - Marco Jantke - - Saem Ghani - - Claudiu Cristea - - Zacharias Luiten - - Sebastian Utz - - Adrien Gallou (agallou) - - Andrea Sprega (asprega) - - Maks Rafalko (bornfree) - - Conrad Kleinespel (conradk) - - Clément LEFEBVRE (nemoneph) - - Viktor Bajraktar (njutn95) - - Walter Dal Mut (wdalmut) - - abluchet - - Ruud Arentsen - - Harald Tollefsen - - PabloKowalczyk - - Matthieu - - ZiYao54 - - Arend-Jan Tetteroo - - Albin Kerouaton - - Sébastien HOUZÉ - - sebastian - - Mbechezi Nawo - - wivaku - - Markus Reinhold - - Jingyu Wang - - es - - steveYeah - - Asrorbek (asrorbek) - - Samy D (dinduks) - - Keri Henare (kerihenare) - - Andre Eckardt (korve) - - Cédric Lahouste (rapotor) - - Samuel Vogel (samuelvogel) - - Osayawe Ogbemudia Terry (terdia) - - Berat Doğan - - Christian Kolb - - Guillaume LECERF - - Alan Scott - - Juanmi Rodriguez Cerón - - twifty - - David Szkiba - - Andy Raines - - François Poguet - - Anthony Ferrara - - Geoffrey Pécro (gpekz) - - Klaas Cuvelier (kcuvelier) - - Flavien Knuchel (knuch) - - Mathieu TUDISCO (mathieutu) - - Dmytro Dzubenko - - Martijn Croonen - - Peter Ward - - markusu49 - - Steve Frécinaux - - Constantine Shtompel - - Jules Lamur - - Renato Mendes Figueiredo - - xdavidwu - - Benjamin RICHARD - - Raphaël Droz - - Vladimir Pakhomchik - - pdommelen - - Eric Stern - - ShiraNai7 - - Cedrick Oka - - Antal Áron (antalaron) - - Guillaume Sainthillier (guillaume-sainthillier) - - Ivan Pepelko (pepelko) - - Vašek Purchart (vasek-purchart) - - Janusz Jabłoński (yanoosh) - - Jens Hatlak - - Fleuv - - Tayfun Aydin - - Łukasz Makuch - - Arne Groskurth - - Ilya Chekalsky - - Ostrzyciel - - George Giannoulopoulos - - Thibault G - - Alexander Pasichnik (alex_brizzz) - - Felix Eymonot (hyanda) - - Luis Ramirez (luisdeimos) - - Ilia Sergunin (maranqz) - - Daniel Richter (richtermeister) - - Sandro Hopf (senaria) - - ChrisC - - André Laugks - - jack.shpartko - - Willem Verspyck - - Kim Laï Trinh - - Johan de Ruijter - - InbarAbraham - - Jason Desrosiers - - m.chwedziak - - marbul - - Filippos Karailanidis - - Andreas Frömer - - Jeroen Bouwmans - - Bikal Basnet - - Philip Frank - - David Brooks - - Lance McNearney - - Illia Antypenko (aivus) - - Jelizaveta Lemeševa (broken_core) - - Dominik Ritter (dritter) - - Frank Neff (fneff) - - Volodymyr Kupriienko (greeflas) - - Ilya Biryukov (ibiryukov) - - Mathieu Ledru (matyo91) - - Roma (memphys) - - Jozef Môstka (mostkaj) - - Florian Caron (shalalalala) - - Serhiy Lunak (slunak) - - Wojciech Błoszyk (wbloszyk) - - Giorgio Premi - - Matthias Bilger - - abunch - - tamcy - - Lukas Naumann - - Mikko Pesari - - Krzysztof Pyrkosz - - Aurélien Fontaine - - ncou - - Ian Carroll - - Dennis Fehr - - caponica - - jdcook - - 🦅KoNekoD - - Daniel Kay (danielkay-cp) - - Matt Daum (daum) - - Malcolm Fell (emarref) - - Alberto Pirovano (geezmo) - - inwebo veritas (inwebo) - - Pascal Woerde (pascalwoerde) - - Pete Mitchell (peterjmit) - - phuc vo (phucwan) - - Tom Corrigan (tomcorrigan) - - Luis Galeas - - Bogdan Scordaliu - - Sven Scholz - - Martin Pärtel - - Daniel Rotter (danrot) - - Frédéric Bouchery (fbouchery) - - Jacek Kobus (jackks) - - Patrick Daley (padrig) - - Phillip Look (plook) - - Foxprodev - - Artfaith - - Tom Kaminski - - developer-av - - Max Summe - - Ema Panz - - Hugo Sales - - Dale.Nash - - DidierLmn - - Pedro Silva - - Chihiro Adachi (chihiro-adachi) - - Clément R. (clemrwan) - - Jeroen de Graaf - - Hossein Hosni - - Ulrik McArdle - - BiaDd - - Oleksii Bulba - - Ramon Cuñat - - mboultoureau - - Raphaëll Roussel - - Vitalii - - Tadcka - - Bárbara Luz - - Abudarham Yuval - - Beth Binkovitz - - adhamiamirhossein - - Maxim Semkin - - Gonzalo Míguez - - Jan Vernarsky - - BrokenSourceCode - - Fabian Haase - - roog - - parinz1234 - - seho-nl - - Romain Geissler - - Martin Auswöger - - Adrien Moiruad - - Viktoriia Zolotova - - Tomaz Ahlin - - Nasim - - Randel Palu - - Anamarija Papić (anamarijapapic) - - AnotherSymfonyUser (arderyp) - - Marcus Stöhr (dafish) - - Daniel González Zaballos (dem3trio) - - Emmanuel Vella (emmanuel.vella) - - Giuseppe Petraroli (gpetraroli) - - Guillaume BRETOU (guiguiboy) - - Ibon Conesa (ibonkonesa) - - Yoann Chocteau (kezaweb) - - Nikita Popov (nikic) - - nuryagdy mustapayev (nueron) - - Carsten Nielsen (phreaknerd) - - Valérian Lepeule (vlepeule) - - Michael Olšavský - - Jay Severson - - Benny Born - - Vincent Vermeulen - - Stefan Moonen - - Emirald Mateli - - Robert - - Ivan Tse - - René Kerner - - Nathaniel Catchpole - - Jontsa - - Igor Plantaš - - upchuk - - Adrien Samson (adriensamson) - - Samuel Gordalina (gordalina) - - Maksym Romanowski (maxromanovsky) - - Nicolas Eeckeloo (neeckeloo) - - Andriy Prokopenko (sleepyboy) - - Dariusz Ruminski - - Starfox64 - - Ivo Valchev - - Thomas Hanke - - ffd000 - - Daniel Tschinder - - Arnaud CHASSEUX - - Zlatoslav Desyatnikov - - Wickex - - tuqqu - - Wojciech Gorczyca - - Ahmad Al-Naib - - Neagu Cristian-Doru (cristian-neagu) - - Mathieu Morlon (glutamatt) - - NIRAV MUKUNDBHAI PATEL (niravpatel919) - - Owen Gray (otis) - - Rafał Muszyński (rafmus90) - - Sébastien Decrême (sebdec) - - Timothy Anido (xanido) - - Robert-Jan de Dreu - - Mara Blaga - - Rick Prent - - skalpa - - Kai - - Bartłomiej Zając - - Pieter Jordaan - - Tournoud (damientournoud) - - Michael Dowling (mtdowling) - - Karlos Presumido (oneko) - - Pierre Foresi (pforesi) - - Tony Vermeiren (tony) - - Bart Wach - - Jos Elstgeest - - Kirill Lazarev - - Thomas Counsell - - Joe - - BilgeXA - - mmokhi - - Serhii Smirnov - - Robert Queck - - Peter Bouwdewijn - - Kurt Thiemann - - Martins Eglitis - - Daniil Gentili - - Eduard Morcinek - - Wouter Diesveld - - Romain - - Matěj Humpál - - Kasper Hansen - - Nico Hiort af Ornäs - - Eddy - - Amine Matmati - - Kristen Gilden - - caalholm - - Nouhail AL FIDI (alfidi) - - Fabian Steiner (fabstei) - - Felipy Amorim (felipyamorim) - - Guillaume Loulier (guikingone) - - Michael Lively (mlivelyjr) - - Pierre Grimaud (pgrimaud) - - Abderrahim (phydev) - - Attila Bukor (r1pp3rj4ck) - - Thomas Boileau (tboileau) - - Alexander Janssen (tnajanssen) - - Thomas Chmielowiec (chmielot) - - Jānis Lukss - - simbera - - Julien BERNARD - - Michael Zangerle - - rkerner - - Alex Silcock - - Raphael Hardt - - Ivan Nemets - - Dave Long - - Qingshan Luo - - Michael Olšavský - - Ergie Gonzaga - - Matthew J Mucklo - - AnrDaemon - - SnakePin - - Matthew Covey - - Tristan Kretzer - - Adriaan Zonnenberg - - Charly Terrier (charlypoppins) - - Dcp (decap94) - - Emre Akinci (emre) - - Rachid Hammaoui (makmaoui) - - Chris Maiden (matason) - - psampaz (psampaz) - - Andrea Ruggiero (pupax) - - Stan Jansen (stanjan) - - Maxwell Vandervelde - - karstennilsen - - kaywalker - - Sebastian Ionescu - - Robert Kopera - - Pablo Ogando Ferreira - - Thomas Ploch - - Victor Prudhomme - - Simon Neidhold - - Wouter Ras - - Gil Hadad - - Valentin VALCIU - - Jeremiah VALERIE - - Alexandre Beaujour - - Franck Ranaivo-Harisoa - - Grégoire Rabasse - - Cas van Dongen - - Patrik Patie Gmitter - - George Yiannoulopoulos - - Yannick Snobbert - - Kevin Dew - - James Cowgill - - Žan V. Dragan - - sensio - - Julien Menth (cfjulien) - - Lyubomir Grozdanov (lubo13) - - Nicolas Schwartz (nicoschwartz) - - Tim Jabs (rubinum) - - Schvoy Norbert (schvoy) - - Stéphane Seng (stephaneseng) - - Peter Schultz - - Robert Korulczyk - - Jonathan Gough - - Benhssaein Youssef - - Benoit Leveque - - bill moll - - chillbram - - Benjamin Bender - - PaoRuby - - Holger Lösken - - Bizley - - Jared Farrish - - Yohann Tilotti - - karl.rixon - - raplider - - Konrad Mohrfeldt - - Lance Chen - - Ciaran McNulty (ciaranmcnulty) - - Dominik Piekarski (dompie) - - Andrew (drew) - - j4nr6n (j4nr6n) - - Rares Sebastian Moldovan (raresmldvn) - - Stelian Mocanita (stelian) - - Gautier Deuette - - dsech - - wallach-game - - Gilbertsoft - - tadas - - Bastien Picharles - - Kirk Madera - - Linas Ramanauskas - - mamazu - - Keith Maika - - izenin - - Mephistofeles - - Oleh Korneliuk - - Emmanuelpcg - - Rini Misini - - Attila Szeremi - - Evgeny Ruban - - Hoffmann András - - LubenZA - - Victor Garcia - - Juan Mrad - - Denis Yuzhanin - - k-sahara - - Flavian Sierk - - Rik van der Heijden - - knezmilos13 - - Thomas Beaujean - - alireza - - Michael Bessolov - - sauliusnord - - Zdeněk Drahoš - - Dan Harper - - moldcraft - - Marcin Kruk - - Antoine Bellion (abellion) - - Ramon Kleiss (akathos) - - Alexey Buyanow (alexbuyanow) - - Antonio Peric-Mazar (antonioperic) - - César Suárez (csuarez) - - Bjorn Twachtmann (dotbjorn) - - Marek Víger (freezy) - - Goran (gog) - - Wahyu Kristianto (kristories) - - Tobias Genberg (lorceroth) - - Michael Simonson (mikes) - - Nicolas Badey (nico-b) - - Florent Blaison (orkin) - - Olivier Scherler (oscherler) - - Flo Gleixner (redflo) - - Romain Jacquart (romainjacquart) - - Shane Preece (shane) - - Stephan Wentz (temp) - - Johannes Goslar - - Mike Gladysch - - Geoff - - georaldc - - wusuopu - - Markus Staab - - Wouter de Wild - - Peter Potrowl - - povilas - - andreybolonin1989@gmail.com - - Gavin Staniforth - - bahram - - Alessandro Tagliapietra (alex88) - - Nikita Starshinov (biji) - - Alex Teterin (errogaht) - - Gunnar Lium (gunnarlium) - - Malte Wunsch (maltewunsch) - - Marie Minasyan (marie.minassyan) - - Pavel Stejskal (spajxo) - - Szymon Kamiński (szk) - - Tiago Garcia (tiagojsag) - - Artiom - - Jakub Simon - - TheMhv - - Eviljeks - - Juliano Petronetto - - robin.de.croock - - Brandon Antonio Lorenzo - - Bouke Haarsma - - Boris Medvedev - - mlievertz - - Radosław Kowalewski - - Enrico Schultz - - tpetry - - Nikita Sklyarov - - JustDylan23 - - Juraj Surman - - Martin Eckhardt - - natechicago - - DaikiOnodera - - Victor - - Andreas Allacher - - Abdelilah Jabri - - Alexis - - Leonid Terentyev - - Sergei Gorjunov - - Jonathan Poston - - Adrian Olek (adrianolek) - - Camille Dejoye (cdejoye) - - cybernet (cybernet2u) - - Jody Mickey (jwmickey) - - Przemysław Piechota (kibao) - - Martin Schophaus (m_schophaus_adcada) - - Martynas Sudintas (martiis) - - Anton Sukhachev (mrsuh) - - Pavlo Pelekh (pelekh) - - Stefan Kleff (stefanxl) - - RichardGuilland - - Marcel Siegert - - ryunosuke - - Bruno BOUTAREL - - Athorcis - - John Stevenson - - everyx - - Richard Heine - - Francisco Facioni (fran6co) - - Stanislav Gamaiunov (happyproff) - - Iwan van Staveren (istaveren) - - Alexander McCullagh (mccullagh) - - Paul L McNeely (mcneely) - - Povilas S. (povilas) - - Laurent Negre (raulnet) - - Sergey Fokin (tyraelqp) - - Victoria Quirante Ruiz (victoria) - - Evrard Boulou - - pborreli - - Ibrahim Bougaoua - - Boris Betzholz - - Eric Caron - - Arnau González - - GurvanVgx - - Jiri Falis - - 2manypeople - - Wing - - Thomas Bibb - - Stefan Koopmanschap - - George Sparrow - - Toro Hill - - Joni Halme - - Matt Farmer - - André Laugks - - catch - - aetxebeste - - Roberto Guido - - ElisDN - - roromix - - Vitali Tsyrkin - - Juga Paazmaya - - Alexandre Segura - - afaricamp - - Josef Cech - - riadh26 - - AntoineDly - - Konstantinos Alexiou - - Andrii Boiko - - Dilek Erkut - - mikocevar - - Harold Iedema - - WaiSkats - - Morimoto Ryosuke - - Ikhsan Agustian - - Benoit Lévêque (benoit_leveque) - - Bernat Llibre Martín (bernatllibre) - - Simon Bouland (bouland) - - Christoph König (chriskoenig) - - Dmytro Pigin (dotty) - - Abdouarrahmane FOUAD (fabdouarrahmane) - - Jakub Janata (janatjak) - - Jm Aribau (jmaribau) - - Maciej Paprocki (maciekpaprocki) - - Matthew Foster (mfoster) - - Paul Seiffert (seiffert) - - Vasily Khayrulin (sirian) - - Stas Soroka (stasyan) - - Thomas Dubuffet (thomasdubuffet) - - Stefan Hüsges (tronsha) - - Jake Bishop (yakobeyak) - - Dan Blows - - popnikos - - Matt Wells - - Nicolas Appriou - - Javier Alfonso Bellota de Frutos - - stloyd - - Tito Costa - - Andreas - - Chris Tickner - - Andrew Coulton - - Ulugbek Miniyarov - - Jeremy Benoist - - Antoine Beyet - - Michal Gebauer - - René Landgrebe - - Phil Davis - - Thiago Melo - - Gleb Sidora - - David Stone - - Giorgio Premi - - Gerhard Seidel (gseidel) - - Jovan Perovic (jperovic) - - Pablo Maria Martelletti (pmartelletti) - - Sebastian Drewer-Gutland (sdg) - - Sander van der Vlugt (stranding) - - casdal - - Florian Bogey - - Waqas Ahmed - - Bert Hekman - - Luis Muñoz - - Matthew Donadio - - Kris Buist - - Houziaux mike - - Phobetor - - Eric Schildkamp - - Yoann MOROCUTTI - - d.huethorst - - Markus - - Zayan Goripov - - agaktr - - Janusz Mocek - - Johannes - - Mostafa - - kernig - - Thomas Chmielowiec - - shdev - - Andrey Ryaguzov - - Gennadi Janzen - - SenTisso - - Stefan - - Peter Bex - - Manatsawin Hanmongkolchai - - Gunther Konig - - Joe Springe - - Mickael GOETZ - - Tobias Speicher - - Jesper Noordsij - - DerStoffel - - Flinsch - - Maciej Schmidt - - botbotbot - - tatankat - - Cláudio Cesar - - Sven Nolting - - Timon van der Vorm - - nuncanada - - Thierry Marianne - - František Bereň - - G.R.Dalenoort - - Jeremiah VALERIE - - Mike Francis - - Nil Borodulia - - Adam Katz - - Almog Baku (almogbaku) - - Boris Grishenko (arczinosek) - - Arrakis (arrakis) - - Danil Khaliullin (bifidokk) - - Benjamin Schultz (bschultz) - - Christian Grasso (chris54721) - - Vladimir Khramtsov (chrome) - - Gerd Christian Kunze (derdu) - - Stephanie Trumtel (einahp) - - Denys Voronin (hurricane) - - Ionel Scutelnicu (ionelscutelnicu) - - Jordan de Laune (jdelaune) - - Juan Gonzalez Montes (juanwilde) - - Kamil Madejski (kmadejski) - - Mathieu Dewet (mdewet) - - none (nelexa) - - Nicolas Tallefourtané (nicolab) - - Botond Dani (picur) - - Rémi Faivre (rfv) - - Radek Wionczek (rwionczek) - - tinect (tinect) - - Nick Stemerdink - - Bernhard Rusch - - David Stone - - Vincent Bouzeran - - fabi - - Grayson Koonce - - Ruben Jansen - - Wissame MEKHILEF - - Mihai Stancu - - shreypuranik - - Thibaut Salanon - - Romain Dorgueil - - Christopher Parotat - - Andrey Helldar - - Dennis Haarbrink - - Daniel Kozák - - Urban Suppiger - - 蝦米 - - Julius Beckmann (h4cc) - - Julien JANVIER (jjanvier) - - Karim Cassam Chenaï (ka) - - Lorenzo Adinolfi (loru88) - - Marcello Mönkemeyer (marcello-moenkemeyer) - - Ahmed Shamim Hassan (me_shaon) - - Michal Kurzeja (mkurzeja) - - Nicolas Bastien (nicolas_bastien) - - Nikola Svitlica (thecelavi) - - Andrew Zhilin (zhil) - - Sjors Ottjes - - azjezz - - VojtaB - - Andy Stanberry - - Felix Marezki - - Normunds - - Yuri Karaban - - Walter Doekes - - Johan - - Thomas Rothe - - Edwin - - Troy Crawford - - Kirill Roskolii - - Jeroen van den Nieuwenhuisen - - nietonfir - - Andriy - - Taylor Otwell - - alefranz - - David Barratt - - Andrea Giannantonio - - Pavel.Batanov - - avi123 - - Pavel Prischepa - - Philip Dahlstrøm - - Pierre Schmitz - - Sami Mussbach - - qzylalala - - alsar - - downace - - Aarón Nieves Fernández - - Mikolaj Czajkowski - - Ahto Türkson - - Paweł Stasicki - - Ph3nol - - Kirill Saksin - - Shiro - - Reda DAOUDI - - Koalabaerchen - - michalmarcinkowski - - Warwick - - Chris - - Farid Jalilov - - Christiaan Wiesenekker - - Ariful Alam - - Florent Olivaud - - Foxprodev - - Eric Hertwig - - JakeFr - - Dmitry Hordinky - - Oliver Klee - - Niels Robin-Aubertin - - Simon Sargeant - - efeen - - Mikko Ala-Fossi - - Jan Christoph Beyer - - withbest - - Nicolas Pion - - Muhammed Akbulut - - Daniel Tiringer - - Xesau - - Koray Zorluoglu - - Roy-Orbison - - Aaron Somi - - kshida - - Yasmany Cubela Medina (bitgandtter) - - Michał Dąbrowski (defrag) - - Aryel Tupinamba (dfkimera) - - Elías (eliasfernandez) - - Hans Höchtl (hhoechtl) - - Simone Fumagalli (hpatoio) - - Brian Graham (incognito) - - Kevin Vergauwen (innocenzo) - - Alessio Baglio (ioalessio) - - Johannes Müller (johmue) - - Jordi Llonch (jordillonch) - - julien_tempo1 (julien_tempo1) - - Roman Igoshin (masterro) - - Nicholas Ruunu (nicholasruunu) - - Pierre Rebeilleau (pierrereb) - - Milos Colakovic (project2481) - - Raphael de Almeida (raphaeldealmeida) - - Rénald Casagraude (rcasagraude) - - Robin Duval (robin-duval) - - Mohammad Ali Sarbanha (sarbanha) - - Sergii Dolgushev (sergii-swds) - - Steeve Titeca (stiteca) - - Thomas Citharel (tcit) - - Artem Lopata (bumz) - - Soha Jin - - alex - - Alex Niedre - - evgkord - - Roman Orlov - - Simon Ackermann - - Andreas Allacher - - VolCh - - Alexey Popkov - - Gijs Kunze - - Artyom Protaskin - - Steven Dubois - - Nathanael d. Noblet - - Yurun - - helmer - - ged15 - - Simon Asika - - CDR - - Daan van Renterghem - - Bálint Szekeres - - Boudry Julien - - amcastror - - Bram Van der Sype (brammm) - - Guile (guile) - - Mark Beech (jaybizzle) - - Julien Moulin (lizjulien) - - Raito Akehanareru (raito) - - Mauro Foti (skler) - - Thibaut Arnoud (thibautarnoud) - - Valmont Pehaut-Pietri (valmonzo) - - Yannick Warnier (ywarnier) - - Jörn Lang - - Kevin Decherf - - Paul LE CORRE - - Christian Weiske - - Maria Grazia Patteri - - klemens - - dened - - muchafm - - jpauli - - Dmitry Korotovsky - - Michael van Tricht - - ReScO - - Tim Strehle - - Sébastien COURJEAN - - cay89 - - Sam Ward - - Hans N. Hjort - - Marko Vušak - - Walther Lalk - - Adam - - Ivo - - vltrof - - Ismo Vuorinen - - Markus Staab - - Valentin - - Gerard - - Sören Bernstein - - michael.kubovic - - devel - - Iain Cambridge - - taiiiraaa - - Ali Tavafi - - gedrox - - Viet Pham - - Alan Bondarchuk - - Pchol - - Benjamin Ellis - - Shamimul Alam - - Cyril HERRERA - - dropfen - - RAHUL K JHA - - Andrey Chernykh - - Edvinas Klovas - - Drew Butler - - Peter Breuls - - Kevin EMO - - Chansig - - Tischoi - - divinity76 - - vdauchy - - Andreas Hasenack - - J Bruni - - Alexey Prilipko - - vlakoff - - Anthony Tenneriello - - thib92 - - Yiorgos Kalligeros - - Rudolf Ratusiński - - Bertalan Attila - - Arek Bochinski - - Rafael Tovar - - Amin Hosseini (aminh) - - AmsTaFF (amstaff) - - Simon Müller (boscho) - - Yannick Bensacq (cibou) - - Cyrille Bourgois (cyrilleb) - - Damien Vauchel (damien_vauchel) - - Dmitrii Fedorenko (dmifedorenko) - - William Pinaud (docfx) - - Frédéric G. Marand (fgm) - - Freek Van der Herten (freekmurze) - - Luca Genuzio (genuzio) - - Ben Gamra Housseine (hbgamra) - - Andrew Marcinkevičius (ifdattic) - - Ioana Hazsda (ioana-hazsda) - - Jan Marek (janmarek) - - Mark de Haan (markdehaan) - - Maxime Corteel (mcorteel) - - Dan Patrick (mdpatrick) - - Mathieu MARCHOIS (mmar) - - Nei Rauni Santos (nrauni) - - Geoffrey Monte (numerogeek) - - Martijn Boers (plebian) - - Plamen Mishev (pmishev) - - Pedro Magalhães (pmmaga) - - Rares Vlaseanu (raresvla) - - Trevor N. Suarez (rican7) - - Sergii Dolgushev (serhey) - - Clément Bertillon (skigun) - - Rein Baarsma (solidwebcode) - - tante kinast (tante) - - Stephen Lewis (tehanomalousone) - - Ahmed HANNACHI (tiecoders) - - Vincent LEFORT (vlefort) - - Walid BOUGHDIRI (walidboughdiri) - - Wim Molenberghs (wimm) - - Darryl Hein (xmmedia) - - Vladimir Sadicov (xtech) - - Marcel Berteler - - Ruud Seberechts - - sdkawata - - Frederik Schmitt - - Peter van Dommelen - - Tim van Densen - - Andrzej - - Alexander Zogheb - - tomasz-kusy - - Rémi Blaise - - Nicolas Séverin - - patrickmaynard - - Houssem - - Joel Marcey - - zolikonta - - Daniel Bartoníček - - Michael Hüneburg - - David Christmann - - root - - pf - - Zoli Konta - - Vincent Chalnot - - Roeland Jago Douma - - Patrizio Bekerle - - Tom Maguire - - Mateusz Lerczak - - Tim Porter - - Richard Quadling - - Will Rowe - - Rainrider - - David Zuelke - - Adrian - - Oliver Eglseder - - neFAST - - Peter Gribanov - - zcodes - - Pierre Rineau - - Florian Morello - - Maxim Lovchikov - - ivelin vasilev - - adenkejawen - - Florent SEVESTRE (aniki-taicho) - - Ari Pringle (apringle) - - Dan Ordille (dordille) - - Jan Eichhorn (exeu) - - Georg Ringer (georgringer) - - Grégory Pelletier (ip512) - - Johan Wilfer (johanwilfer) - - John Nickell (jrnickell) - - Martin Mayer (martin) - - Grzegorz Łukaszewicz (newicz) - - Nico Müller (nicomllr) - - Omar Yepez (oyepez003) - - Jonny Schmid (schmidjon) - - Toby Griffiths (tog) + - Simon DELICATA + - vitaliytv + - Franck RANAIVO-HARISOA (franckranaivo) + - Yi-Jyun Pan + - Philippe Segatori + - Jayson Xu (superjavason) + - Oleksandr Barabolia (oleksandrbarabolia) + - Sébastien Despont (bouillou) + - Maxime Douailin + - benjaminmal + - Dominik Ulrich + - Kay Wei + - Reen Lokum + - Michał Jusięga + - Marc Laporte + - Jean Pasdeloup + - Roy de Vos Burchart + - Jon Gotlin (jongotlin) + - Andrey Sevastianov + - James Johnston + - Joost van Driel (j92) + - Khoo Yong Jun + - Adrian Nguyen (vuphuong87) + - Julien Fredon + - Paulo Ribeiro (paulo) + - Sebastian Blum + - Matthew Davis (mdavis1982) + - Abhoryo + - Xavier Leune (xleune) + - Marcos Gómez Vilches (markitosgv) + - Baptiste CONTRERAS + - Julien Turby + - Lorenzo Millucci (lmillucci) + - Ricky Su (ricky) + - Cristoforo Cervino (cristoforocervino) + - scyzoryck + - Arno Geurts + - Florian Hermann (fhermann) + - Kyle Evans (kevans91) + - Max Rath (drak3) + - marie + - Stéphane Escandell (sescandell) + - Pavol Tuka + - Fractal Zombie + - Philipp Keck + - Noémi Salaün (noemi-salaun) + - Gennady Telegin + - Benedikt Lenzen (demigodcode) + - Alexandre Dupuy (satchette) + - Michel Hunziker + - Malte Blättermann + - Ilya Levin (ilyachase) + - Simeon Kolev (simeon_kolev9) + - Jonas Elfering + - Mihai Stancu + - louismariegaborit + - Nahuel Cuesta (ncuesta) + - Ruben Gonzalez (rubenruateltek) + - Chris Boden (cboden) + - Kuba Werłos (kuba) + - Johnson Page (jwpage) + - Jacques MOATI (jmoati) + - EStyles (insidestyles) + - Christophe Villeger (seragan) + - Harry Walter (haswalt) + - Krystian Marcisz (simivar) + - David Fuhr + - Hany el-Kerdany + - Dhananjay Goratela + - Åsmund Garfors + - Maxime COLIN (maximecolin) + - ywisax + - Javier López (loalf) + - Xavier Briand (xavierbriand) + - Douglas Reith (douglas_reith) + - Reinier Kip + - noniagriconomie + - Bill Hance (billhance) + - Jérôme Tamarelle (jtamarelle-prismamedia) + - Carlos Pereira De Amorim (epitre) + - Emil Masiakowski + - Geoffrey Brier (geoffrey-brier) + - Balazs Csaba + - Nykopol (nykopol) + - Tony Tran + - Alex Bogomazov (alebo) + - Martins Sipenko + - Michael Hüneburg + - root + - Vincent Chalnot + - Roeland Jago Douma + - Patrizio Bekerle + - Tom Maguire + - Mateusz Lerczak + - Tim Porter + - Richard Quadling + - Will Rowe + - Rainrider + - David Zuelke + - Adrian + - Oliver Eglseder + - neFAST + - Peter Gribanov + - zcodes + - Pierre Rineau + - Maxim Lovchikov + - adenkejawen + - Florent SEVESTRE (aniki-taicho) + - Jan Eichhorn (exeu) + - Georg Ringer (georgringer) + - Johan Wilfer (johanwilfer) + - Martin Mayer (martin) + - Ruud Seberechts + - ivelin vasilev + - John Nickell (jrnickell) + - Toby Griffiths (tog) + - Paul Le Corre + - Grzegorz Łukaszewicz (newicz) + - Nico Müller (nicomllr) + - Omar Yepez (oyepez003) + - carlos-ea - Ashura - Götz Gottwald - Alessandra Lai @@ -3192,10 +1548,8 @@ The Symfony Connect username in parenthesis allows to get more information - Thanh Trần - Robert Campbell - Matt Lehner - - carlos-ea - Olexandr Kalaidzhy - Helmut Januschka - - Jérémy Benoist - Hein Zaw Htet™ - Ruben Kruiswijk - Cosmin-Romeo TANASE @@ -3205,15 +1559,15 @@ The Symfony Connect username in parenthesis allows to get more information - youssef saoubou - Joseph Maarek - Alexander Menk - - Alex Pods - timaschew - Jelle Kapitein - Jochen Mandl - - elattariyassine - Asrorbek Sultanov - Marin Nicolae - Gerrit Addiks - Buster Neece + - lerminou + - Jenne van der Meer - Albert Prat - Alessandro Loffredo - Ian Phillips @@ -3221,16 +1575,18 @@ The Symfony Connect username in parenthesis allows to get more information - Remi Collet - Haritz - Matthieu Prat - - Brieuc Thomas - zors1 - Peter Simoncic - - lerminou - Adam Bramley + - thecaliskan - Ahmad El-Bardan + - martijn - mantulo + - Andrew Brown - pdragun - - Paul Le Corre + - Erik van Wingerden - Noel Light-Hilary + - Gilles Gauthier - Filipe Guerra - Jean Ragouin - Gerben Wijnja @@ -3241,12 +1597,8 @@ The Symfony Connect username in parenthesis allows to get more information - Per Modin - David Windell - Frank Jogeleit - - Ondřej Frei - Gabriel Birke - Derek Bonner - - martijn - - Jenne van der Meer - - annesosensio - NothingWeAre - Storkeus - goabonga @@ -3265,7 +1617,6 @@ The Symfony Connect username in parenthesis allows to get more information - sam-bee - Vlad Dumitrache - wetternest - - Erik van Wingerden - Valouleloup - Pathpat - Jaymin G @@ -3276,678 +1627,4455 @@ The Symfony Connect username in parenthesis allows to get more information - Matheus Gontijo - Gerrit Drost - Linnaea Von Lavia - - Andrew Brown - Javan Eskander - Lenar Lõhmus - - Cristian Gonzalez - MusikAnimal - AlberT - hainey - - Juan M Martínez - - Gilles Gauthier + - Dominik Hajduk (dominikalp) + - gondo (gondo) - Benjamin Franzke - Pavinthan + - David Joos (djoos) - Sylvain METAYER + - Dennis Smink (dsmink) - ddebree - Gyula Szucs - - Dmitriy - Tomas Liubinas + - Jan Hort + - Klaas Naaijkens + - Bojan + - Rafał + - Adria Lopez (adlpz) + - Adrien Peyre (adpeyre) + - Alexandre Jardin (alexandre.jardin) + - Bart Brouwer (bartbrouwer) + - baron (bastien) + - Bastien Clément (bastienclement) + - Rosio (ben-rosio) + - Simon Paarlberg (blamh) + - Anne-Sophie Bachelard + - Masao Maeda (brtriver) + - Alexander Dmitryuk (coden1) + - Valery Maslov (coderberg) + - Damien Harper (damien.harper) + - Darius Leskauskas (darles) + - david perez (davidpv) + - Denis Klementjev (dklementjev) + - Dominik Pesch (dombn) + - Tomáš Polívka (draczris) + - Duncan de Boer (farmer-duck) + - Franz Liedke (franzliedke) + - Gaylord Poillon (gaylord_p) + - Javier Núñez Berrocoso (javiernuber) + - Hadrien Cren (hcren) + - Gusakov Nikita (hell0w0rd) + - Halil Hakan Karabay (hhkrby) + - Jaap van Otterdijk (jaapio) + - Jelle Bekker (jbekker) + - Dave Heineman (dheineman) + - Giovanni Albero (johntree) + - Mikhail Prosalov (mprosalov) + - Jorge Martin (jorgemartind) + - Kubicki Kamil (kubik) + - Ronny López (ronnylt) + - Joeri Verdeyen (jverdeyen) + - Kevin Herrera (kherge) + - guangwu + - Luis Ramón López López (lrlopez) + - Vladislav Nikolayev (luxemate) + - Martin Mandl (m2mtech) + - Mehdi Mabrouk (mehdidev) + - Bart Reunes (metalarend) + - Muriel (metalmumu) + - Michael Pohlers (mick_the_big) + - Misha Klomp (mishaklomp) + - mlpo (mlpo) + - Marcel Pociot (mpociot) + - Ulrik Nielsen (mrbase) + - Marek Šimeček (mssimi) + - Cayetano Soriano Gallego (neoshadybeat) + - Artem (nexim) + - Olivier Laviale (olvlvl) + - Pierre Gasté (pierre_g) + - Pablo Monterde Perez (plebs) + - Pierre-Olivier Vares (povares) + - Jimmy Leger (redpanda) + - Julius (sakalys) + - Dmitry (staratel) + - Marcin Szepczynski (szepczynski) + - Simone Di Maulo (toretto460) + - Cyrille Jouineau (tuxosaurus) + - Florian Morello + - Wim Godden (wimg) + - Yorkie Chadwick (yorkie76) + - Maxime Aknin (3m1x4m) + - Lauris Binde (laurisb) + - Zakaria AMMOURA (zakariaamm) + - Shrey Puranik + - Pavel Barton + - michal + - GuillaumeVerdon + - valmonzo + - Dmitry Danilson + - Marien Fressinaud + - ureimers + - akimsko + - Youpie + - Jason Stephens + - Korvin Szanto + - Taylan Kasap + - Michael Orlitzky + - Nicolas A. Bérard-Nault + - Quentin Favrie + - Matthias Derer + - Francois Martin + - Saem Ghani + - Kévin + - Stefan Oderbolz + - Tamás Szigeti + - Gabriel Moreira + - Alexey Popkov + - ChS + - Jannik Zschiesche + - Alexis MARQUIS + - Joseph Deray + - Damian Sromek + - Evgeniy Tetenchuk + - Sjoerd Adema + - Kai Eichinger + - Evgeniy Koval + - Lars Moelleken + - dasmfm + - Karel Syrový + - Claas Augner + - Mathias Geat + - neodevcode + - Angel Fernando Quiroz Campos (angelfqc) + - Arnaud Buathier (arnapou) + - Curtis (ccorliss) + - chesteroni (chesteroni) + - Mauricio Lopez (diaspar) + - HADJEDJ Vincent (hadjedjvincent) + - Ismail Asci (ismailasci) + - Jeffrey Moelands (jeffreymoelands) + - Ondřej Mirtes (mirtes) + - vladyslavstartsev + - ToshY + - Paulius Jarmalavičius (pjarmalavicius) + - Ramon Ornelas (ramonornela) + - helmi + - Sylvain Lorinet + - Ruslan Zavacky (ruslanzavacky) + - Jakub Caban (lustmored) + - Stefano Cappellini (stefano_cappellini) + - Till Klampaeckel (till) + - Tobias Weinert (tweini) + - Wotre + - Sepehr Lajevardi + - George Bateman + - Xavier HAUSHERR + - Edwin Hageman + - Mantas Urnieža + - temperatur + - Paul Andrieux + - Sezil + - misterx + - Cas + - Vincent Godé - Ivo Valchev - - Jan Hort - - Klaas Naaijkens - - Bojan - - Rafał - - Adria Lopez (adlpz) - - Adrien Peyre (adpeyre) - - Aaron Scherer (aequasi) - - Alexandre Jardin (alexandre.jardin) - - Bart Brouwer (bartbrouwer) - - baron (bastien) - - Bastien Clément (bastienclement) - - Rosio (ben-rosio) - - Simon Paarlberg (blamh) - - Masao Maeda (brtriver) - - Alexander Dmitryuk (coden1) - - Valery Maslov (coderberg) - - Damien Harper (damien.harper) - - Darius Leskauskas (darles) - - david perez (davidpv) - - David Joos (djoos) - - Denis Klementjev (dklementjev) - - Dominik Pesch (dombn) - - Dominik Hajduk (dominikalp) - - Tomáš Polívka (draczris) - - Dennis Smink (dsmink) - - Duncan de Boer (farmer-duck) - - Franz Liedke (franzliedke) - - Gaylord Poillon (gaylord_p) - - gondo (gondo) - - Joris Garonian (grifx) - - Grummfy (grummfy) - - Hadrien Cren (hcren) - - Gusakov Nikita (hell0w0rd) - - Halil Hakan Karabay (hhkrby) - - Oz (import) - - Jaap van Otterdijk (jaapio) - - Javier Núñez Berrocoso (javiernuber) - - Jelle Bekker (jbekker) - - Giovanni Albero (johntree) - - Jorge Martin (jorgemartind) - - Joeri Verdeyen (jverdeyen) + - Michael Steininger + - Nardberjean + - Dylan + - ghazy ben ahmed + - Karolis + - Myke79 + - jersoe + - Brian Debuire + - Eric Grimois + - Christian Schiffler + - Piers Warmers + - Pavol Tuka + - klyk50 + - Colin Michoudet + - jc + - BenjaminBeck + - Aurelijus Rožėnas + - Beno!t POLASZEK + - Armando + - Jordan Hoff + - znerol + - Christian Eikermann + - Sergei Shitikov + - Steffen Keuper + - Jens Schulze + - Tema Yud + - Olatunbosun Egberinde + - Jiri Korenek + - Alexis Lefebvre + - Johannes + - Dominic Tubach + - Andras Debreczeni + - sarah-eit + - rhel-eo + - patrick-mcdougle + - Vladimir Sazhin + - lol768 + - Michel Bardelmeijer + - Menno Holtkamp + - Tomas Kmieliauskas + - Dariusz Czech + - Ikko Ashimine + - Alexandru Bucur + - Erwin Dirks + - cmfcmf + - Markus Ramšak + - Billie Thompson + - Philipp + - jamogon + - Tom Hart + - Vyacheslav Slinko + - Benjamin Laugueux + - Jakub Chábek + - Johannes + - Jörg Rühl + - George Dietrich + - jannick-holm + - wesleyh + - Ser5 + - Michael Hudson-Doyle + - Matthew Burns + - Daniel Bannert + - Karim Miladi + - Michael Genereux + - Greg Korba + - Camille Islasse + - Tyler Stroud + - Clemens Krack + - Bruno Baguette + - Jack Wright + - MrNicodemuz + - demeritcowboy + - Paweł Tomulik + - Eric J. Duran + - omerida + - Anatol Belski + - Blackfelix + - Pavel Witassek + - Michal Forbak + - Drew Butler + - Alexey Berezuev + - pawel-lewtak + - Pierrick Charron + - Steve Müller + - Andras Ratz + - Benjamin RICHARD + - andreabreu98 + - Jérémie Broutier + - Marcus + - gechetspr + - brian978 + - Michael Schneider + - n-aleha + - Richard Čepas + - Talha Zekeriya Durmuş + - Javier + - Alexis BOYER + - bch36 + - Kaipi Yann + - wiseguy1394 + - adam-mospan + - AUDUL + - Steve Hyde + - AbdelatifAitBara + - nerdgod + - Sam Williams + - Ettore Del Negro + - Guillaume Aveline + - Adrian Philipp + - James Michael DuPont + - Simone Ruggieri + - Kasperki + - dima-gr + - Daniel Strøm + - Rodolfo Ruiz + - tsilefy + - Enrico + - Adrien Foulon + - Sylvain Just + - Ryan Rud + - vlechemin + - Brian Corrigan + - Ladislav Tánczos + - Brian Freytag + - Skorney + - Lucas Matte + - Success Go + - fmarchalemisys + - MGatner + - mieszko4 + - Steve Preston + - ibasaw + - Wojciech Skorodecki + - Neophy7e + - Evert Jan Hakvoort + - rewrit3 + - Filippos Karailanidis + - David Ronchaud + - A. Pauly + - Chris McGehee + - Shaun Simmons + - Bogdan + - Pierre-Louis LAUNAY + - Arseny Razin + - Benjamin Rosenberger + - Michael Gwynne + - Eduardo Conceição + - changmin.keum + - Jon Cave + - Sébastien HOUZE + - Abdulkadir N. A. + - Markus Klein + - Adam Klvač + - Bruno Nogueira Nascimento Wowk + - Tomanhez + - satalaondrej + - jonmldr + - Yevgen Kovalienia + - Lebnik + - Shude + - RTUnreal + - Richard Hodgson + - Sven Fabricius + - Ondřej Führer + - Sema + - Ayke Halder + - Thorsten Hallwas + - Brian Freytag + - Arend Hummeling + - Joseph FRANCLIN + - Marco Pfeiffer + - Alex Nostadt + - Michael Squires + - Egor Gorbachev + - Julian Krzefski + - Derek Stephen McLean + - Norman Soetbeer + - zorn + - Yuriy Potemkin + - Emilie Lorenzo + - enomotodev + - Vincent + - Benjamin Long + - Fabio Panaccione + - Kévin Gonella + - Ben Miller + - Peter Gribanov + - Matteo Galli + - Bart Ruysseveldt + - Ash014 + - kwiateusz + - Nowfel2501 + - Ilya Bulakh + - David Soria Parra + - Arrilot + - Dawid Nowak + - Simon Frost + - Gert de Pagter + - Sergiy Sokolenko + - Harry Wiseman + - Cantepie + - llupa + - djama + - detinkin + - Loenix + - Ahmed Abdulrahman + - Penny Leach + - Kevin Mian Kraiker + - Yurii K + - Richard Trebichavský + - g123456789l + - Mark Ogilvie + - Jonathan Vollebregt + - oscartv + - Michal Čihař + - parhs + - Emilien Escalle + - jwaguet + - Diego Campoy + - Oncle Tom + - Sam Anthony + - Christian Stocker + - Oussama Elgoumri + - David Lima + - Steve Marvell + - Lesnykh Ilia + - Shyim + - darnel + - Nicolas + - Sergio Santoro + - tirnanog06 + - Andrejs Leonovs + - Alfonso Fernández García + - phc + - Дмитрий Пацура + - Signor Pedro + - Lin Lu + - RFreij + - Matthias Larisch + - Maxime P + - Sean Templeton + - Willem Mouwen + - db306 + - Bohdan Pliachenko + - Dr. Gianluigi "Zane" Zanettini + - Michaël VEROUX + - Julia + - arduanov + - Fabien + - David Courtey (david-crty) + - Martin Komischke + - Yendric + - Loïc Vernet (coil) + - ADmad + - Gerard Berengue Llobera (bere) + - Hugo Posnic + - Nicolas Roudaire + - Marc Jauvin + - Matthias Meyer + - Temuri Takalandze (abgeo) + - Bernard van der Esch (adeptofvoltron) + - Andreas Forsblom (aforsblo) + - Aleksejs Kovalovs (aleksejs1) + - Alex Olmos (alexolmos) + - Robin Kanters (anddarerobin) + - Antoine (antoinela_adveris) + - Juan Ases García (ases) + - Siragusa (asiragusa) + - Daniel Basten (axhm3a) + - Albert Bakker (babbert) + - Benedict Massolle (bemas) + - Ronny (big-r) + - Bernd Matzner (bmatzner) + - Vladimir Vasilev (bobahvas) + - Anton (bonio) + - Bram Tweedegolf (bram_tweedegolf) + - Brandon Kelly (brandonkelly) + - Choong Wei Tjeng (choonge) + - Bermon Clément (chou666) + - Citia (citia) + - Kousuke Ebihara (co3k) + - Christoph Vincent Schaefer (cvschaefer) + - Kamil Piwowarski (cyklista) + - Damon Jones (damon__jones) + - David Gorges (davidgorges) + - Alexandre Fiocre (demos77) + - Gustavo Adrian + - Chris Shennan (chrisshennan) + - Abdouni Karim (abdounikarim) + - Łukasz Giza (destroyer) + - Dušan Kasan (dudo1904) + - Joao Paulo V Martins (jpjoao) + - Sebastian Landwehr (dword123) + - Adel ELHAIBA (eadel) + - Julien Manganne (juuuuuu) + - Damián Nohales (eagleoneraptor) + - Gerry Vandermaesen (gerryvdm) + - Elliot Anderson (elliot) + - Yohan Giarelli (frequence-web) + - Erwan Nader (ernadoo) + - Ian Littman (iansltx) + - Fabien D. (fabd) + - Carsten Eilers (fnc) + - Sorin Gitlan (forapathy) + - Fraller Balázs (fracsi) + - Jorge Maiden (jorgemaiden) + - Lesueurs Frédéric (fredlesueurs) + - Arash Tabrizian (ghost098) + - Greg Szczotka (greg606) + - Nathan DIdier (icz) + - Vladislav Krupenkin (ideea) + - Peter Orosz (ill_logical) + - Ilia Lazarev (ilzrv) + - Imangazaliev Muhammad (imangazaliev) + - wesign (inscrutable01) + - j0k (j0k) + - joris de wit (jdewit) + - JG (jege) + - Jose Manuel Gonzalez (jgonzalez) + - Pierre-Chanel Gauthier (kmecnin) + - Joachim Krempel (jkrempel) + - Joshua Behrens (joshuabehrens) + - Justin Rainbow (jrainbow) + - JuntaTom (juntatom) + - Ismail Faizi (kanafghan) + - Karolis Daužickas (kdauzickas) + - Kérian MONTES-MORIN (kerianmm) + - Krzysztof Menżyk (krymen) + - Nicholas Byfleet (nickbyfleet) + - Ala Eddine Khefifi (nayzo) + - Kenjy Thiébault (kthiebault) + - Matt Ketmo (mattketmo) + - samuel laulhau (lalop) + - Matt Drollette (mdrollette) + - Laurent Bachelier (laurentb) + - Adam Monsen (meonkeys) + - Luís Cobucci (lcobucci) + - Aurimas Rimkus (patrikas) + - Petr Jaroš (petajaros) + - Seyedramin Banihashemi (ramin) + - Mehdi Achour (machour) + - Jérémy (libertjeremy) + - Mamikon Arakelyan (mamikon) + - Philipp Hoffmann (philipphoffmann) + - Daniel Perez Pinazo (pitiflautico) + - scourgen hung (scourgen) + - Mark Schmale (masch) + - Moritz Borgmann (mborgmann) + - Ralf Kühnel (ralfkuehnel) + - Marco Wansinck (mwansinck) + - Mike Milano (mmilano) + - Guillaume Lajarige (molkobain) + - Diego Aguiar (mollokhan) + - Steffen Persch (n3o77) + - emilienbouard (neime) + - Nicolas Bondoux (nsbx) + - Cedric Kastner (nurtext) + - ollie harridge (ollietb) + - Pawel Szczepanek (pauluz) + - Sebastian Busch (sebu) + - Philippe Degeeter (pdegeeter) + - PLAZANET Pierre (pedrotroller) + - Christian López Espínola (penyaskito) + - Pavel Golovin (pgolovin) + - Alex Carol (picard89) + - Igor Tarasov (polosatus) + - Maksym Pustynnikov (pustynnikov) + - Ramazan APAYDIN (rapaydin) + - Babichev Maxim (rez1dent3) + - Sergey Stavichenko (sergey_stavichenko) + - Andrea Giuliano (shark) + - André Filipe Gonçalves Neves (seven) + - Schuyler Jager (sjager) + - craigmarvelley + - Ángel Guzmán Maeso (shakaran) + - Bruno Ziegler (sfcoder) + - Tom Newby (tomnewbyau) + - Verlhac Gaëtan (viviengaetan) + - Şəhriyar İmanov (shehriyari) + - Roman Tymoshyk (tymoshyk) + - Volker (skydiablo) + - Julien Sanchez (sumbobyboys) + - Ron Gähler (t-ronx) + - Guillermo Gisinger (t3chn0r) + - Tomáš Korec (tomkorec) + - Andrew Clark (tqt_andrew_clark) + - Aaron Piotrowski (trowski) + - David Lumaye (tux1124) + - Moritz Kraft (userfriendly) + - Víctor Mateo (victormateo) + - Vincent MOULENE (vints24) + - David Grüner (vworldat) + - Eugene Babushkin (warl) + - Wouter Sioen (wouter_sioen) + - Xavier Amado (xamado) + - Jesper Søndergaard Pedersen (zerrvox) + - Florent Cailhol + - Konrad + - Kevin Weber + - Kovacs Nicolas + - eminjk + - Stano Turza + - Antoine Leblanc + - Andre Johnson + - MaPePeR + - Andreas Streichardt + - Alexandre Segura + - Marco Pfeiffer + - Vivien + - Pascal Hofmann + - david-binda + - smokeybear87 + - damaya + - szymek + - Marc Bennewitz + - Adam Elsodaney (archfizz) + - Carl Julian Sauter + - Dionysis Arvanitis + - Alexandru Năstase + - Sergey Fedotov + - Gabriel Solomon (gabrielsolomon) + - Konstantin Scheumann + - Josef Hlavatý + - Michael + - fh-github@fholzhauer.de + - rogamoore + - AbdElKader Bouadjadja + - ddegentesh + - DSeemiller + - Jan Emrich + - Anne-Julia Seitz + - mindaugasvcs + - Mark Topper + - Xavier REN + - Kevin Meijer + - max + - Ahmad Mayahi (ahmadmayahi) + - Mohamed Karnichi (amiral) + - Andrew Carter (andrewcarteruk) + - Gregório Bonfante Borba (bonfante) + - Bogdan Rancichi (devck) + - Daniel Kolvik (dkvk) + - Marc Lemay (flug) + - Courcier Marvin (helyakin) + - Henne Van Och (hennevo) + - Muharrem Demirci (mdemirci) + - Evgeny Z (meze) + - Aleksandar Dimitrov (netbull) + - Pierre-Henry Soria 🌴 (pierrehenry) + - Pierre Geyer (ptheg) + - Thomas BERTRAND (sevrahk) + - Vladislav (simpson) + - Marin Bînzari (spartakusmd) + - Stefanos Psarras (stefanos) + - Matej Žilák (teo_sk) + - Vladislav Vlastovskiy (vlastv) + - Yannick Vanhaeren (yvh) + - Ignacio Alveal - Kevin Verschaeve (keversc) - - Kevin Herrera (kherge) - - Kubicki Kamil (kubik) - - Lauris Binde (laurisb) - - Luis Ramón López López (lrlopez) - - Vladislav Nikolayev (luxemate) - - Martin Mandl (m2mtech) - - Mehdi Mabrouk (mehdidev) - - Bart Reunes (metalarend) - - Muriel (metalmumu) - - Michael Pohlers (mick_the_big) - - Misha Klomp (mishaklomp) - - mlpo (mlpo) - - Marcel Pociot (mpociot) - - Mikhail Prosalov (mprosalov) - - Ulrik Nielsen (mrbase) - - Marek Šimeček (mssimi) + - RENAUDIN Xavier (xorrox) + - Pontus Mårdnäs + - Ryan Linnit + - Sebastian Göttschkes (sgoettschkes) + - es + - David Szkiba + - Vladimir Pakhomchik + - drublic + - Simon / Yami + - Maciej Paprocki (maciekpaprocki) + - Abdelhakim ABOULHAJ + - PatrickRedStar + - Gary Houbre (thegarious) + - Zan Baldwin (zanderbaldwin) + - Thomas Cochard (tcochard) + - Mark Pedron (markpedron) + - Guillaume Loulier (guikingone) + - Ricardo de Vries (ricardodevries) + - Tristan Bessoussa (sf_tristanb) + - Alessandro Tagliapietra (alex88) + - Aaron Scherer (aequasi) + - Chris Maiden (matason) + - Michal Trojanowski + - Quentin Moreau (sheitak) + - Stefan Kruppa + - Julien Boudry + - insekticid + - Romain Pierre + - alexpods + - dantleech + - Jontsa + - JK Groupe + - cgonzalez + - Raphael Davaillaud + - Radosław Kowalewski + - Dmitry Hordinky + - William Pinaud (docfx) + - Paul Ferrett + - MightyBranch + - victor-prdh + - Jeremy Benoist + - Miloš Milutinović + - pizzaminded + - johnstevenson + - Roromix + - Nathaniel Catchpole + - gauss + - Per Sandström (per) + - azine + - Goran Juric + - heccjj + - Igor Plantaš + - Arkalo2 + - Jiri Falis + - taiiiraaa + - Ali Tavafi - Dmitriy Tkachenko (neka) - - Cayetano Soriano Gallego (neoshadybeat) - - Artem (nexim) - - Nicolas ASSING (nicolasassing) - - Olivier Laviale (olvlvl) - - Pierre Gasté (pierre_g) - - Pablo Monterde Perez (plebs) - - Pierre-Olivier Vares (povares) - - Jimmy Leger (redpanda) - - Ronny López (ronnylt) - - Julius (sakalys) - - Dmitry (staratel) - - Marcin Szepczynski (szepczynski) - - Tito Miguel Costa (titomiguelcosta) - - Simone Di Maulo (toretto460) - - Cyrille Jouineau (tuxosaurus) - - Lajos Veres (vlajos) - - Vladimir Chernyshev (volch) - - Wim Godden (wimg) - - Yorkie Chadwick (yorkie76) - - Zakaria AMMOURA (zakariaamm) - - Maxime Aknin (3m1x4m) - - Pavel Barton - - Exploit.cz - - GuillaumeVerdon - - Dmitry Danilson - - Marien Fressinaud - - ureimers - - akimsko - - Youpie - - Jason Stephens - - Korvin Szanto - - srsbiz - - Taylan Kasap - - Michael Orlitzky - - Nicolas A. Bérard-Nault - - Quentin Favrie - - Matthias Derer - - Francois Martin - - vladyslavstartsev + - Peter Zwosta + - Jeroen De Dauw (jeroendedauw) + - Wing + - Kai Dederichs + - Andrii Dembitskyi + - Enrico Schultz + - tpetry + - Nikita Sklyarov + - Dmitriy Derepko + - ondrowan + - Ninos + - Dmitry Simushev + - Juraj Surman + - Wang Jingyu + - JustDylan23 + - DaikiOnodera + - Aleksey Prilipko + - Victor + - Andreas Allacher + - Dan Kadera + - Christian Morgan + - Alexis + - withbest + - Abdelilah Jabri + - Ben Johnson + - Mickael Perraud + - Frank Schulze (xit) + - soyuka + - Yann LUCAS (drixs6o9) + - Farhad Hedayatifard + - Vincent Chalamon + - Nicolas Appriou + - Sorin Pop (sorinpop) + - Stewart Malik + - Alan ZARLI + - Renan Taranto (renan-taranto) + - Valérian Galliat + - Stefan Graupner (efrane) + - Charly Goblet (_mocodo) + - Anton Dyshkant + - Adrien Chinour + - Jiří Bok + - Thomas Jarrand + - Baptiste Leduc (bleduc) + - Piotr Zajac + - Patrick Kaufmann + - Ismail Özgün Turan (dadeather) + - Rafael Villa Verde + - Zoran Makrevski (zmakrevski) + - Kirill Nesmeyanov (serafim) + - Gemorroj (gemorroj) + - Reece Fowell (reecefowell) + - Htun Htun Htet (ryanhhh91) + - Guillaume Gammelin + - Elías Fernández + - d-ph + - Samael tomas + - Mahmoud Mostafa (mahmoud) + - Damien Fernandes + - Mateusz Żyła (plotkabytes) + - Jean-Christophe Cuvelier [Artack] + - Rene de Lima Barbosa (renedelima) + - Rikijs Murgs + - Mikkel Paulson + - WoutervanderLoop.nl + - Yewhen Khoptynskyi (khoptynskyi) + - Mihail Krasilnikov (krasilnikovm) + - Alex Vo (votanlean) + - Jonas Claes + - iamvar + - Amaury Leroux de Lens (amo__) + - Piergiuseppe Longo + - Nicolas Lemoine + - Christian Jul Jensen + - Valentin Barbu (jimie) + - Lukas Kaltenbach + - Daniel Iwaniec + - Alexandre GESLIN + - The Whole Life to Learn + - Pierre Tondereau + - Joel Lusavuvu (enigma97) + - kurozumi (kurozumi) + - Liverbool (liverbool) + - Aurélien MARTIN + - Malte Schlüter + - Jules Matsounga (hyoa) + - Nicolas Attard (nicolasattard) + - Jérôme Nadaud (jnadaud) + - Frank Naegler + - Sam Malone + - Ha Phan (haphan) + - Chris Jones (leek) + - neghmurken + - stefan.r + - Florian Cellier + - xaav + - Alexandre Tranchant (alexandre_t) + - Ahmed Abdou + - shreyadenny + - Pieter + - Kevin Auivinet + - ergiegonzaga + - Leonid Terentyev + - Luciano Mammino (loige) + - Radosław Benkel + - Laurent Clouet + - Dennis Tobar + - Ganesh Chandrasekaran (gxc4795) + - Michael Tibben + - Icode4Food (icode4food) + - Hallison Boaventura (hallisonboaventura) + - Billie Thompson + - Mas Iting + - Thomas Ferney (thomasf) + - Grégoire Hébert (gregoirehebert) + - Louis-Proffit + - Albion Bame (abame) + - Ferenczi Krisztian (fchris82) + - Guillaume Smolders (guillaumesmo) + - Iliya Miroslavov Iliev (i.miroslavov) + - Sander Marechal + - Ivan Nemets + - Franz Wilding (killerpoke) + - Artyum Petrov + - Oleg Golovakhin (doc_tr) + - Bert ter Heide (bertterheide) + - Kevin Nadin (kevinjhappy) + - jean pasqualini (darkilliant) + - Safonov Nikita (ns3777k) + - Mei Gwilym (meigwilym) + - Jitendra Adhikari (adhocore) + - Kevin Jansen + - Nicolas Martin (cocorambo) + - Tom Panier (neemzy) + - luffy1727 + - LHommet Nicolas (nicolaslh) + - fabios + - eRIZ + - Sander Coolen (scoolen) + - Vic D'Elfant (vicdelfant) + - Amirreza Shafaat (amirrezashafaat) + - Maarten Nusteling (nusje2000) + - Gordienko Vladislav + - Peter van Dommelen + - Ahmed EBEN HASSINE (famas23) + - Hubert Moreau (hmoreau) + - Marvin Butkereit + - dantleech + - Anton Babenko (antonbabenko) + - Chris de Kok + - Eduard Bulava (nonanerz) + - Damien Fayet (rainst0rm) + - Andreas Kleemann (andesk) + - Valentin + - Dalibor Karlović + - Nicolas Valverde + - Eric Krona + - Alex Plekhanov + - Igor Timoshenko (igor.timoshenko) + - Hryhorii Hrebiniuk + - Pierre-Emmanuel CAPEL + - Mario Blažek (marioblazek) + - Manuele Menozzi + - Ashura + - Yevhen Sidelnyk + - “teerasak” + - Irmantas Šiupšinskas (irmantas) + - Benoit Mallo + - Charles-Henri Bruyand + - Danilo Silva + - Giuseppe Campanelli + - Konstantin S. M. Möllers (ksmmoellers) + - Ken Stanley + - ivan + - Zachary Tong (polyfractal) + - linh + - Oleg Krasavin (okwinza) + - Jure (zamzung) + - Michael Nelson + - Nsbx + - hamza + - Kajetan Kołtuniak (kajtii) + - Dan (dantleech) + - Artem (digi) + - Sander Goossens (sandergo90) + - Rudy Onfroy + - DerManoMann + - MatTheCat + - Erfan Bahramali + - boite + - tamar peled + - Sergei Gorjunov + - tamirvs + - Silvio Ginter + - David Wolter (davewww) + - Peter Culka + - Arman + - MGDSoft + - Abdiel Carrazana (abdielcs) + - alanzarli + - joris + - Anna Filina (afilina) + - Vadim Tyukov (vatson) + - Yannick + - Gabi Udrescu + - Adamo Crespi (aerendir) + - Sortex + - chispita + - Wojciech Sznapka + - Emmanuel Dreyfus + - Luis Pabon (luispabon) + - boulei_n + - Shaun Simmons + - Ariel J. Birnbaum + - Patrick Luca Fazzi (ap3ir0n) + - Tim Lieberman + - Danijel Obradović + - Pablo Borowicz + - Ben Oman + - Ondřej Frei + - Bruno Rodrigues de Araujo (brunosinister) + - Máximo Cuadros (mcuadros) + - Jacek Wilczyński (jacekwilczynski) + - Christoph Kappestein + - Camille Baronnet + - EXT - THERAGE Kevin + - julien.galenski + - Florian Guimier + - Maxime PINEAU + - Igor Kokhlov (verdet) + - Christian Neff (secondtruth) + - Chris Tiearney + - Oliver Hoff + - Minna N + - andersmateusz + - Laurent Moreau + - Faton (notaf) + - Tom Houdmont + - mark burdett + - Piotr Antosik (antek88) + - Laurent G. (laurentg) + - Ville Mattila + - Jean-Baptiste Nahan + - SOEDJEDE Felix (fsoedjede) + - Thomas Decaux + - Mert Simsek (mrtsmsk0) + - Nicolas Macherey + - Asil Barkin Elik (asilelik) + - Nacho Martin (nacmartin) + - Bhujagendra Ishaya + - gr8b + - Guido Donnari + - Markus Baumer + - Jérôme Dumas + - Georgi Georgiev + - Norbert Schultheisz + - otsch + - Christophe Meneses (c77men) + - Jeremy David (jeremy.david) + - adnen chouibi + - Andrei O + - Łukasz Chruściel (lchrusciel) + - Max Beutel + - Jordi Rejas + - Troy McCabe + - gstapinato + - gr1ev0us + - Léo VINCENT + - mlazovla + - Alejandro Diaz Torres + - Bradley Zeggelaar + - Karl Shea + - Bouke Haarsma + - Valentin + - Nathan Sepulveda + - Jan Vernieuwe (vernija) + - Antanas Arvasevicius + - Adam Kiss + - Pierre Dudoret + - Thomas + - j.schmitt + - Maximilian Berghoff (electricmaxxx) + - Volker Killesreiter (ol0lll) + - Evgeny Anisiforov + - Tristan Pouliquen + - Dominic Luidold + - Thomas Bibaut + - Thibaut Chieux + - mwos + - Aydin Hassan + - Vedran Mihočinec (v-m-i) + - Jonathan Poston + - Sébastien Lévêque (legenyes) + - Rafał Treffler + - Ken Marfilla (marfillaster) + - Sergey Novikov (s12v) + - Arkadiusz Rzadkowolski (flies) + - creiner + - Marcos Quesada (marcos_quesada) + - Jan Pintr + - Jean-Guilhem Rouel (jean-gui) + - ProgMiner + - remieuronews + - Christian + - Matthew (mattvick) + - MARYNICH Mikhail (mmarynich-ext) + - Viktor Novikov (nowiko) + - Paul Mitchum (paul-m) + - Angel Koilov (po_taka) + - Marek Binkowski + - Max Grigorian (maxakawizard) + - allison guilhem + - benatespina (benatespina) + - Denis Kop + - Fabrice Locher + - Konstantin Chigakov + - Kamil Szalewski (szal1k) + - Yoann MOROCUTTI + - Ivan Yivoff + - jfcixmedia + - Martijn Evers + - Alexander Onatskiy + - Philipp Fritsche + - Léon Gersen + - tarlepp + - Giuseppe Arcuti + - Dustin Wilson + - Saif Eddin G + - Claus Due (namelesscoder) + - Alexandru Patranescu + - ju1ius + - Denis Golubovskiy (bukashk0zzz) + - Serge (nfx) + - Oksana Kozlova (oksanakozlova) + - Mikkel Paulson + - Dan Wilga + - Jon Green (jontjs) + - Michał Strzelecki + - Marcin Chwedziak + - Bert Ramakers + - Alex Demchenko + - Hugo Fonseca (fonsecas72) + - Marc Duboc (icemad) + - Martynas Narbutas + - Timothée BARRAY + - Nilmar Sanchez Muguercia + - Pierre LEJEUNE (darkanakin41) + - Bailey Parker + - curlycarla2004 + - Javier Ledezma + - Antanas Arvasevicius + - Kris Kelly + - Eddie Abou-Jaoude (eddiejaoude) + - Haritz Iturbe (hizai) + - Rutger Hertogh + - Diego Sapriza + - Joan Cruz + - inspiran + - Richard van Velzen + - Cristobal Dabed + - Daniel Mecke (daniel_mecke) + - Serhii Polishchuk (spolischook) + - Tadas Gliaubicas (tadcka) + - Thanos Polymeneas (thanos) + - Atthaphon Urairat + - Benoit Garret + - Maximilian Ruta (deltachaos) + - Jakub Sacha + - Julius Kiekbusch + - Kamil Musial + - Lucas Bustamante + - Olaf Klischat + - orlovv + - Adrian Olek (adrianolek) + - EdgarPE + - Claude Dioudonnat + - Jonathan Hedstrom + - Peter Smeets (darkspartan) + - Julien Bianchi (jubianchi) + - Michael Dawart (mdawart) + - Robert Meijers + - Tijs Verkoyen + - James Sansbury + - hjkl + - Thijs Reijgersberg + - Nicolas Jourdan (nicolasjc) + - Florian Heller + - Evgeny Efimov (edefimov) + - Oleksii Svitiashchuk + - Péter Buri (burci) + - Yann Rabiller (einenlum) + - Alexander Cheprasov + - Andrew Tch + - Peter Trebaticky + - Rodrigo Díez Villamuera (rodrigodiez) + - Brad Treloar + - Nicolas Sauveur (baishu) + - pritasil + - Abderrahman DAIF (death_maker) + - Stephen Clouse + - e-ivanov + - Nathanaël Martel (nathanaelmartel) + - Benjamin Dos Santos + - GagnarTest (gagnartest) + - Jochen Bayer (jocl) + - Tomas Javaisis + - HellFirePvP + - Constantine Shtompel + - VAN DER PUTTE Guillaume (guillaume_vdp) + - Patrick Carlo-Hickman + - Bruno MATEU + - Jeremy Bush + - Lucas Bäuerle + - Laurens Laman + - Thomason, James + - Dario Savella + - Gordienko Vladislav + - Joas Schilling + - Ener-Getick + - Markus Thielen + - Moza Bogdan (bogdan_moza) + - Viacheslav Sychov + - Zuruuh + - Helmut Hummel (helhum) + - Matt Brunt + - David Vancl + - Carlos Ortega Huetos + - jack.thomas (jackthomasatl) + - John VanDeWeghe + - kaiwa + - Charles Sanquer (csanquer) + - Albert Ganiev (helios-ag) + - Neil Katin + - Oleg Mifle + - David Otton + - V1nicius00 + - Will Donohoe + - Takashi Kanemoto (ttskch) + - peter + - Andoni Larzabal (andonilarz) + - Tugba Celebioglu + - Yann (yann_eugone) + - Jeroen de Boer + - Staormin + - Oleg Sedinkin (akeylimepie) + - Dan Brown + - Jérémy Jourdin (jjk801) + - David de Boer (ddeboer) + - BRAMILLE Sébastien (oktapodia) + - maxime.perrimond + - Guillem Fondin (guillemfondin) + - Markkus Millend + - Artem Kolesnikov (tyomo4ka) + - Gustavo Adrian + - Jorrit Schippers (jorrit) + - Matthias Neid + - danilovict2 + - Kuzia + - spdionis + - rchoquet + - v.shevelev + - rvoisin + - gitlost + - Taras Girnyk + - Simon Mönch + - Barthold Bos + - cthulhu + - Wolfgang Klinger (wolfgangklingerplan2net) + - Rémi Leclerc + - Jan Vernarsky + - Ionut Cioflan + - John Edmerson Pizarra + - Sergio + - Jonas Hünig + - Mehrdad + - Amine Yakoubi + - Eno Mullaraj (emullaraj) + - Arnaud CHASSEUX + - Eduardo García Sanz (coma) + - Makdessi Alex + - Dmitrii Baranov + - fduch (fduch) + - Aleksei Lebedev + - dlorek + - Stuart Fyfe + - Jason Schilling (chapterjason) + - Yannick + - Camille Dejoye (cdejoye) + - Pawel Smolinski + - Nathan PAGE (nathix) + - Nicolas Fabre (nfabre) + - Arnaud + - Klaus Purer + - Vladimir Mantulo (mantulo) + - Dmitrii Lozhkin + - Radoslaw Kowalewski + - Marion Hurteau (marionleherisson) + - Gilles Doge (gido) + - Oscar Esteve (oesteve) + - Sobhan Sharifi (50bhan) + - Peter Potrowl + - abulford + - Ilya Vertakov + - Brooks Boyd + - Axel Venet + - Roger Webb + - Yury (daffox) + - John Espiritu (johnillo) + - Tomasz (timitao) + - Nguyen Tuan Minh (tuanminhgp) + - Oxan van Leeuwen + - pkowalczyk + - dbrekelmans + - Mykola Zyk + - Soner Sayakci + - Max Voloshin (maxvoloshin) + - Raul Rodriguez (raul782) + - Piet Steinhart + - mousezheng + - mshavliuk + - Rémy LESCALLIER + - Kacper Gunia (cakper) + - Derek Lambert (dlambert) + - Peter Thompson (petert82) + - Victor Macko (victor_m) + - error56 + - Felicitus + - Jorge Vahldick (jvahldick) + - Krzysztof Przybyszewski (kprzybyszewski) + - Boullé William (williamboulle) + - Bart Baaten + - Clement Herreman (clemherreman) + - Frederic Godfrin + - Dalibor Karlović + - Paul Matthews + - Jakub Kisielewski + - Vacheslav Silyutin + - Aleksandr Dankovtsev + - Maciej Zgadzaj + - David Legatt (dlegatt) + - Alain Flaus (halundra) + - Arthur Woimbée + - tsufeki + - Théo DELCEY + - Philipp Strube + - Wim Hendrikx + - Andrii Serdiuk (andreyserdjuk) + - dangkhoagms (dangkhoagms) + - Jesper Noordsij + - Dan Ionut Dumitriu (danionut90) + - Evgeny (disparity) + - Floran Brutel (notFloran) (floran) + - Vladislav Rastrusny (fractalizer) + - Vlad Gapanovich (gapik) + - nyro (nyro) + - Konstantin Bogomolov + - Marco + - Marc Torres + - Mark Spink + - Alberto Aldegheri + - Cesar Scur (cesarscur) + - Cyril Vermandé (cyve) + - Daniele Orru' (danydev) + - Raul Garcia Canet (juagarc4) + - Dmitri Petmanson + - Tobias Stöckler + - Alexandre Melard + - Rafał Toboła + - Dominik Schwind (dominikschwind) + - Stefano A. (stefano93) + - PierreRebeilleau + - AlbinoDrought + - Sergey Yuferev + - Monet Emilien + - voodooism + - Mario Young + - cybernet (cybernet2u) + - martkop26 + - Orestis + - Raphaël Davaillaud + - Pablo Schläpfer + - Sander Hagen + - Alexander Menk + - Agustin Gomes + - Peter Jaap Blaakmeer + - Prasetyo Wicaksono (jowy) + - cilefen (cilefen) + - Mo Di (modi) + - ConneXNL + - Victor Truhanovich (victor_truhanovich) + - Adam Wójs (awojs) + - Tomasz Szymczyk (karion) + - Christian Rishøj + - Nikos Charalampidis + - Caligone + - Ismail Turan + - Patrick Berenschot + - SuRiKmAn + - matze + - Xavier RENAUDIN + - Christian Wahler (christian) + - Jelte Steijaert (jelte) + - Maxime AILLOUD (mailloud) + - David Négrier (moufmouf) + - Quique Porta (quiqueporta) + - Tobias Feijten (tobias93) + - mohammadreza honarkhah + - Jessica F Martinez + - paullallier + - Artem Oliinyk (artemoliynyk) + - Andrea Quintino (dirk39) + - Andreas Heigl (heiglandreas) + - Alex Vasilchenko + - sez-open + - fruty + - Aharon Perkel + - Justin Reherman (jreherman) + - Miłosz Guglas (miloszowi) + - Rubén Calvo (rubencm) + - Abdul.Mohsen B. A. A + - Cédric Girard + - Robert Worgul + - Swen van Zanten + - Malaney J. Hill + - Robert Korulczyk + - Patryk Kozłowski + - Alexandre Pavy + - Zander Baldwin + - Tim Ward + - Jeffrey Cafferata (jcidnl) + - Adiel Cristo (arcristo) + - Andrei Igna + - Christian Flach (cmfcmf) + - Marcin Nowak + - Mark van den Berg + - Fabian Kropfhamer (fabiank) + - Junaid Farooq (junaidfarooq) + - Pavel Starosek (octisher) + - Oriol Mangas Abellan (oriolman) + - Tatsuya Tsuruoka + - omniError + - László GÖRÖG + - djordy + - Mihai Nica (redecs) + - Adam Prickett + - Luke Towers + - Wojciech Zimoń + - Vladimir Melnik + - Anton Kroshilin + - Pierre Tachoire + - Juan Traverso + - Dawid Sajdak + - Maxime THIRY + - Norman Soetbeer + - Ludek Stepan + - Benjamin BOUDIER + - Frederik Schwan + - Aaron Stephens (astephens) + - Craig Menning (cmenning) + - Balázs Benyó (duplabe) + - Erika Heidi Reinaldo (erikaheidi) + - William Thomson (gauss) + - Javier Espinosa (javespi) + - Marc J. Schmidt (marcjs) + - František Maša + - Sebastian Schwarz + - Flohw + - karolsojko - Saem Ghani - - Kévin - - Stefan Oderbolz - - valmonzo - - Tamás Szigeti - - Gabriel Moreira - - Alexey Popkov - - ChS - - toxxxa - - michal - - Jannik Zschiesche - - Alexis MARQUIS - - Joseph Deray - - Damian Sromek - - Ben - - Evgeniy Tetenchuk - - Sjoerd Adema - - Shrey Puranik - - Kai Eichinger - - Evgeniy Koval - - Lars Moelleken - - dasmfm - - Karel Syrový - - Claas Augner - - Mathias Geat - - neodevcode - - Angel Fernando Quiroz Campos (angelfqc) - - Arnaud Buathier (arnapou) - - Curtis (ccorliss) - - chesteroni (chesteroni) - - Mauricio Lopez (diaspar) - - HADJEDJ Vincent (hadjedjvincent) - - Daniele Cesarini (ijanki) - - Ismail Asci (ismailasci) - - Jeffrey Moelands (jeffreymoelands) - - Jakub Caban (lustmored) - - Ondřej Mirtes (mirtes) - - Paulius Jarmalavičius (pjarmalavicius) - - Ramon Ornelas (ramonornela) - - Ricardo de Vries (ricardodevries) - - Ruslan Zavacky (ruslanzavacky) - - Stefano Cappellini (stefano_cappellini) - - Thomas Dutrion (theocrite) - - Till Klampaeckel (till) - - Tobias Weinert (tweini) - - Wotre - - goohib - - Tom Counsell - - Sepehr Lajevardi - - George Bateman - - Xavier HAUSHERR - - Edwin Hageman - - Mantas Urnieža - - temperatur - - ToshY - - Paul Andrieux - - Sezil - - misterx - - Cas - - arend - - Vincent Godé - - helmi - - Michael Steininger - - Nardberjean - - Dylan - - ghazy ben ahmed - - Karolis - - Myke79 - - jersoe - - Brian Debuire - - Eric Grimois - - Christian Schiffler - - Piers Warmers - - Sylvain Lorinet - - Pavol Tuka - - klyk50 - - Colin Michoudet - - jc - - BenjaminBeck - - Aurelijus Rožėnas - - Beno!t POLASZEK - - Armando - - Jordan Hoff - - znerol - - Christian Eikermann - - Sergei Shitikov - - Steffen Keuper - - Kai Eichinger - - Antonio Angelino - - Jens Schulze - - Tema Yud - - Matt Fields - - Olatunbosun Egberinde - - Johannes - - Andras Debreczeni - - Knallcharge - - Vladimir Sazhin - - Michel Bardelmeijer - - Tomas Kmieliauskas - - Ikko Ashimine - - Erwin Dirks - - Markus Ramšak - - Billie Thompson - - Philipp - - lol768 - - jamogon - - Tom Hart - - Vyacheslav Slinko - - Benjamin Laugueux - - guangwu - - Lane Shukhov - - Jakub Chábek - - William Pinaud (DocFX) + - Marco Jantke + - Maks Rafalko (bornfree) + - alifanau + - Claudiu Cristea + - Jonathan Gough + - Samy D (dinduks) + - Zacharias Luiten + - Clément LEFEBVRE (nemoneph) + - Sebastian Utz + - Adrien Gallou (agallou) + - twifty + - Andrea Sprega (asprega) + - Conrad Kleinespel (conradk) + - Viktor Bajraktar (njutn95) + - Walter Dal Mut (wdalmut) + - abluchet + - Ruud Arentsen + - Harald Tollefsen + - PabloKowalczyk + - Matthieu + - Arend-Jan Tetteroo + - Albin Kerouaton + - sebastian + - Mbechezi Nawo + - wivaku + - Markus Reinhold + - steveYeah + - Asrorbek (asrorbek) + - Ross Tuck + - Keri Henare (kerihenare) + - Andre Eckardt (korve) + - Cédric Lahouste (rapotor) + - Samuel Vogel (samuelvogel) + - Osayawe Ogbemudia Terry (terdia) + - Berat Doğan + - Christian Kolb + - Guillaume LECERF + - Alan Scott + - markusu49 + - Juanmi Rodriguez Cerón + - Andy Raines + - François Poguet + - Anthony Ferrara + - Geoffrey Pécro (gpekz) + - Klaas Cuvelier (kcuvelier) + - Flavien Knuchel (knuch) + - Mathieu TUDISCO (mathieutu) + - Dmytro Dzubenko + - Martijn Croonen + - Peter Ward + - Steve Frécinaux + - Constantine Shtompel + - Jules Lamur + - Volodymyr Kupriienko (greeflas) + - Renato Mendes Figueiredo + - Sagrario Meneses + - Illia Antypenko (aivus) + - Vašek Purchart (vasek-purchart) + - xdavidwu + - Alexander Pasichnik (alex_brizzz) + - Raphaël Droz + - Antal Áron (antalaron) + - Dominik Ritter (dritter) + - ShiraNai7 + - Cedrick Oka + - Guillaume Sainthillier (guillaume-sainthillier) + - Ivan Pepelko (pepelko) + - Janusz Jabłoński (yanoosh) + - Jens Hatlak + - Fleuv + - Tayfun Aydin + - Łukasz Makuch + - Arne Groskurth + - pthompson + - Ilya Chekalsky + - Ostrzyciel + - George Giannoulopoulos + - Thibault G + - Luis Ramirez (luisdeimos) + - Ilia Sergunin (maranqz) + - Daniel Richter (richtermeister) + - Sandro Hopf (senaria) + - ChrisC + - André Laugks + - jack.shpartko + - Mathieu Ledru (matyo91) + - Willem Verspyck + - Kim Laï Trinh + - Johan de Ruijter + - InbarAbraham + - Jason Desrosiers + - m.chwedziak + - marbul + - Andreas Frömer + - Jeroen Bouwmans + - Bikal Basnet + - Philip Frank + - David Brooks + - Lance McNearney + - Jelizaveta Lemeševa (broken_core) + - Daniel Rotter (danrot) + - jprivet-dev + - Ilya Biryukov (ibiryukov) + - Frank Neff (fneff) + - Ema Panz + - Roma (memphys) + - Dale.Nash + - Jozef Môstka (mostkaj) + - Daniel Tschinder + - Wojciech Błoszyk (wbloszyk) + - Florian Caron (shalalalala) + - Serhiy Lunak (slunak) + - Martin Pärtel + - Giorgio Premi + - Tom Corrigan (tomcorrigan) + - abunch + - 🦅KoNekoD + - Lukas Naumann + - Mikko Pesari + - Krzysztof Pyrkosz + - ncou + - Ian Carroll + - Dennis Fehr + - jdcook + - Daniel Kay (danielkay-cp) + - Matt Daum (daum) + - Malcolm Fell (emarref) + - Alberto Pirovano (geezmo) + - inwebo veritas (inwebo) + - Pascal Woerde (pascalwoerde) + - Pete Mitchell (peterjmit) + - phuc vo (phucwan) + - Luis Galeas + - CDR + - Bogdan Scordaliu + - Sven Scholz + - Frédéric Bouchery (fbouchery) + - Jacek Kobus (jackks) + - Patrick Daley (padrig) + - Phillip Look (plook) + - Foxprodev + - Artfaith + - Tom Kaminski + - developer-av + - Max Summe + - DidierLmn + - Pedro Silva + - Ivan Tse + - Chihiro Adachi (chihiro-adachi) + - Clément R. (clemrwan) + - Yoann Chocteau (kezaweb) + - Jeroen de Graaf + - Emmanuel Vella (emmanuel.vella) + - Hossein Hosni + - Marcus Stöhr (dafish) + - Ulrik McArdle + - BiaDd + - Jay Severson + - Oleksii Bulba + - Raphaëll Roussel + - Ramon Cuñat + - mboultoureau + - AnotherSymfonyUser (arderyp) + - Vitalii + - Tadcka + - Bárbara Luz + - Abudarham Yuval + - Beth Binkovitz + - adhamiamirhossein + - Maxim Semkin + - Gonzalo Míguez + - Jan Vernarsky + - Fabian Haase + - roog + - parinz1234 + - seho-nl + - Romain Geissler + - Viktoriia Zolotova + - Tomaz Ahlin + - Nasim + - Randel Palu + - Anamarija Papić (anamarijapapic) + - Daniel González Zaballos (dem3trio) + - Przemysław Piechota (kibao) + - Giuseppe Petraroli (gpetraroli) + - Ibon Conesa (ibonkonesa) + - Nikita Popov (nikic) + - nuryagdy mustapayev (nueron) + - Carsten Nielsen (phreaknerd) + - Valérian Lepeule (vlepeule) + - Vincent Vermeulen + - Stefan Moonen + - Robert Meijers + - Emirald Mateli + - René Kerner + - Michael Olšavský + - upchuk + - Tony Vermeiren (tony) + - Adrien Samson (adriensamson) + - Samuel Gordalina (gordalina) + - Nicolas Eeckeloo (neeckeloo) + - Andriy Prokopenko (sleepyboy) + - Dariusz Ruminski + - Starfox64 + - Ivo Valchev + - Thomas Hanke + - ffd000 + - Zlatoslav Desyatnikov + - Wickex + - tuqqu + - Wojciech Gorczyca + - Ahmad Al-Naib + - Neagu Cristian-Doru (cristian-neagu) + - Mathieu Morlon (glutamatt) + - NIRAV MUKUNDBHAI PATEL (niravpatel919) + - Owen Gray (otis) + - Sébastien Decrême (sebdec) + - Timothy Anido (xanido) + - Mara Blaga + - Rick Prent + - skalpa + - Bartłomiej Zając + - Pieter Jordaan + - Tournoud (damientournoud) + - Michael Dowling (mtdowling) + - Romain + - Karlos Presumido (oneko) + - Pierre Foresi (pforesi) + - Bart Wach + - Jos Elstgeest + - Kirill Lazarev + - Joe + - BilgeXA + - mmokhi + - Serhii Smirnov + - Robert Queck + - Peter Bouwdewijn + - Kurt Thiemann + - Daniil Gentili + - Thomas Counsell + - Pierre Grimaud (pgrimaud) + - Eduard Morcinek + - Wouter Diesveld + - Sebastian Ionescu + - Thomas Ploch + - Matěj Humpál + - Kristen Gilden + - Nico Hiort af Ornäs + - Eddy + - Felipy Amorim (felipyamorim) + - Amine Matmati + - Kasper Hansen + - Benny Born + - Thomas Boileau (tboileau) + - caalholm + - Hugo Sales + - Nouhail AL FIDI (alfidi) + - Michael Lively (mlivelyjr) + - Abderrahim (phydev) + - Attila Bukor (r1pp3rj4ck) + - Mickael GOETZ + - Alexander Janssen (tnajanssen) + - Thomas Chmielowiec (chmielot) + - Jānis Lukss + - Julien BERNARD + - Michael Zangerle + - rkerner + - Alex Silcock + - Raphael Hardt + - Ivan Nemets + - Dave Long + - Qingshan Luo + - Matthew J Mucklo + - AnrDaemon + - SnakePin + - Matthew Covey + - Tristan Kretzer + - Adriaan Zonnenberg + - Charly Terrier (charlypoppins) + - Dcp (decap94) + - Emre Akinci (emre) + - Rachid Hammaoui (makmaoui) + - psampaz (psampaz) + - Andrea Ruggiero (pupax) + - Stan Jansen (stanjan) + - Maxwell Vandervelde + - karstennilsen + - kaywalker + - Robert Kopera + - Jody Mickey (jwmickey) + - Victor Prudhomme + - Wouter Ras + - Simon Neidhold + - Patrik Patie Gmitter + - j4nr6n (j4nr6n) + - Gil Hadad + - Stelian Mocanita (stelian) + - Valentin VALCIU + - Franck Ranaivo-Harisoa + - Jeremiah VALERIE + - Alexandre Beaujour + - Martins Eglitis + - Grégoire Rabasse + - Cas van Dongen + - George Yiannoulopoulos + - Kevin Dew + - James Cowgill + - Žan V. Dragan + - sensio + - Julien Menth (cfjulien) + - Nicolas Schwartz (nicoschwartz) + - Tim Jabs (rubinum) + - Schvoy Norbert (schvoy) + - Aurélien Fontaine + - Stéphane Seng (stephaneseng) + - Benhssaein Youssef + - Benoit Leveque + - bill moll + - chillbram + - Benjamin Bender + - PaoRuby + - Holger Lösken + - Bizley + - Jared Farrish + - karl.rixon + - Konrad Mohrfeldt + - Lance Chen + - Ciaran McNulty (ciaranmcnulty) + - Dominik Piekarski (dompie) + - Andrew (drew) + - Rares Sebastian Moldovan (raresmldvn) + - Gautier Deuette + - dsech + - wallach-game + - Gilbertsoft + - Matthias Bilger + - tadas + - Bastien Picharles + - Linas Ramanauskas + - Martin Schophaus (m_schophaus_adcada) + - Olivier Scherler (oscherler) + - mamazu + - Marek Víger (freezy) + - Keith Maika + - izenin + - Mephistofeles + - Oleh Korneliuk + - Emmanuelpcg + - Rini Misini + - Attila Szeremi + - Pablo Ogando Ferreira + - Hoffmann András + - LubenZA + - Victor Garcia + - Juan Mrad + - Denis Yuzhanin + - k-sahara + - Flavian Sierk + - Rik van der Heijden + - Thomas Beaujean + - alireza + - Michael Bessolov + - sauliusnord + - Zdeněk Drahoš + - Dan Harper + - moldcraft + - Marcin Kruk + - Antoine Bellion (abellion) + - Ramon Kleiss (akathos) + - Alexey Buyanow (alexbuyanow) + - Antonio Peric-Mazar (antonioperic) + - Bjorn Twachtmann (dotbjorn) + - Goran (gog) + - Wahyu Kristianto (kristories) + - Tobias Genberg (lorceroth) + - Nicolas Badey (nico-b) + - Florent Blaison (orkin) + - Flo Gleixner (redflo) + - Romain Jacquart (romainjacquart) + - Shane Preece (shane) + - Stephan Wentz (temp) + - Johannes Goslar + - Mike Gladysch + - Geoff + - georaldc + - wusuopu + - Markus Staab + - Peter Potrowl + - Juliano Petronetto + - povilas + - Martynas Sudintas (martiis) + - Marie Minasyan (marie.minassyan) + - Gavin Staniforth + - Anton Sukhachev (mrsuh) + - bahram + - Gunnar Lium (gunnarlium) + - Pavlo Pelekh (pelekh) + - Nikita Starshinov (biji) + - andreybolonin1989@gmail.com + - Kirk Madera + - Alex Teterin (errogaht) + - Stefan Kleff (stefanxl) + - Boris Betzholz + - Marcel Siegert + - Kélian Bousquet (kells) + - RichardGuilland + - Sergey Fokin (tyraelqp) + - Pavel Stejskal (spajxo) + - Arnau González + - ryunosuke + - Tiago Garcia (tiagojsag) + - TheMhv + - Eviljeks + - everyx + - Richard Heine + - Francisco Facioni (fran6co) + - Stanislav Gamaiunov (happyproff) + - Iwan van Staveren (istaveren) + - Alexander McCullagh (mccullagh) + - Paul L McNeely (mcneely) + - Povilas S. (povilas) + - Laurent Negre (raulnet) + - Victoria Quirante Ruiz (victoria) + - Evrard Boulou + - pborreli + - Ibrahim Bougaoua + - Eric Caron + - GurvanVgx + - 2manypeople + - Thomas Bibb + - Athorcis + - Szymon Kamiński (szk) + - Stefan Koopmanschap + - George Sparrow + - Chris Tickner + - Toro Hill + - Matt Farmer + - Benoit Lévêque (benoit_leveque) + - André Laugks + - aetxebeste + - Andrew Coulton + - Roberto Guido + - Wouter de Wild + - mikocevar + - ElisDN + - Vitali Tsyrkin + - Juga Paazmaya + - Alexandre Segura + - afaricamp + - Josef Cech + - riadh26 + - AntoineDly + - Konstantinos Alexiou + - Andrii Boiko + - Dilek Erkut + - Harold Iedema + - WaiSkats + - Morimoto Ryosuke + - Ikhsan Agustian + - raplider + - Simon Bouland (bouland) + - Christoph König (chriskoenig) + - Dmytro Pigin (dotty) + - Abdouarrahmane FOUAD (fabdouarrahmane) + - Jakub Janata (janatjak) + - Jm Aribau (jmaribau) + - Matthew Foster (mfoster) + - Tobias Speicher + - Paul Seiffert (seiffert) + - Vasily Khayrulin (sirian) + - Stas Soroka (stasyan) + - Thomas Dubuffet (thomasdubuffet) + - Stefan Hüsges (tronsha) + - Jake Bishop (yakobeyak) + - Dan Blows + - popnikos + - Matt Wells + - Nicolas Appriou + - Javier Alfonso Bellota de Frutos + - stloyd + - Tito Costa + - Andreas + - Ulugbek Miniyarov + - Antoine Beyet + - Michal Gebauer + - Gerhard Seidel (gseidel) + - René Landgrebe + - Phil Davis + - Houziaux mike + - Thiago Melo + - Gleb Sidora + - Thomas Chmielowiec + - David Stone + - Giorgio Premi + - Jovan Perovic (jperovic) + - Pablo Maria Martelletti (pmartelletti) + - Sander van der Vlugt (stranding) + - Sebastian Drewer-Gutland (sdg) + - casdal + - Waqas Ahmed + - Bert Hekman + - Luis Muñoz + - Matthew Donadio + - Kris Buist + - Phobetor + - Eric Schildkamp + - Yoann MOROCUTTI + - d.huethorst + - Markus + - DerStoffel + - agaktr + - Janusz Mocek - Johannes - - Jörg Rühl - - George Dietrich - - jannick-holm - - wesleyh - - Menno Holtkamp - - Ser5 - - Michael Hudson-Doyle - - Matthew Burns - - Daniel Bannert - - Karim Miladi - - Michael Genereux - - Greg Korba - - Camille Islasse - - patrick-mcdougle - - Tyler Stroud - - Dariusz Czech - - Clemens Krack - - Bruno Baguette - - Jack Wright - - MrNicodemuz - - Anonymous User - - demeritcowboy - - Paweł Tomulik - - Eric J. Duran - - Blackfelix - - Pavel Witassek - - Alexandru Bucur - - Alexis Lefebvre - - cmfcmf - - sarah-eit - - Michal Forbak - - CarolienBEER + - Mostafa + - kernig + - shdev + - Andrey Ryaguzov + - Gennadi Janzen + - SenTisso + - Peter Bex + - Manatsawin Hanmongkolchai + - Gunther Konig + - Joe Springe + - Jesper Noordsij + - Jeremiah VALERIE + - Flinsch + - Maciej Schmidt + - botbotbot + - tatankat + - Cláudio Cesar + - Sven Nolting + - Timon van der Vorm + - nuncanada + - František Bereň + - G.R.Dalenoort + - Mike Francis + - Adrien Moiruad + - Nil Borodulia + - Vladimir Khramtsov (chrome) + - Adam Katz + - Julius Beckmann (h4cc) + - Almog Baku (almogbaku) + - Boris Grishenko (arczinosek) + - Arrakis (arrakis) + - Andrey Helldar + - Danil Khaliullin (bifidokk) + - Lorenzo Adinolfi (loru88) + - Benjamin Schultz (bschultz) + - Christian Grasso (chris54721) + - Gerd Christian Kunze (derdu) + - Stephanie Trumtel (einahp) + - Denys Voronin (hurricane) + - Ionel Scutelnicu (ionelscutelnicu) + - Juan Gonzalez Montes (juanwilde) + - Kamil Madejski (kmadejski) + - Mathieu Dewet (mdewet) + - none (nelexa) + - Nicolas Tallefourtané (nicolab) + - Botond Dani (picur) + - Rémi Faivre (rfv) + - Radek Wionczek (rwionczek) + - tinect (tinect) + - Nick Stemerdink + - Bernhard Rusch + - David Stone + - Vincent Bouzeran + - Ruben Jansen + - Thibaut Salanon + - Romain Dorgueil + - Christopher Parotat + - Dennis Haarbrink + - Daniel Kozák + - Urban Suppiger + - Julien JANVIER (jjanvier) + - Karim Cassam Chenaï (ka) + - Ahmed Shamim Hassan (me_shaon) + - Mikko Ala-Fossi + - Marcello Mönkemeyer (marcello-moenkemeyer) + - Michal Kurzeja (mkurzeja) + - nietonfir + - Nikola Svitlica (thecelavi) + - Nicolas Bastien (nicolas_bastien) + - Sjors Ottjes + - VojtaB + - Andy Stanberry + - Felix Marezki + - Normunds + - Yuri Karaban + - Walter Doekes + - Thomas Rothe + - Edwin + - Troy Crawford + - Kirill Roskolii + - Jeroen van den Nieuwenhuisen + - Andriy + - Taylor Otwell + - Ph3nol + - alefranz + - David Barratt + - Andrea Giannantonio + - Pavel.Batanov + - avi123 + - Pavel Prischepa + - Philip Dahlstrøm + - Pierre Schmitz + - Sami Mussbach + - qzylalala + - alsar + - Aarón Nieves Fernández + - Ahto Türkson + - Paweł Stasicki + - Kirill Saksin + - Shiro + - Reda DAOUDI + - michalmarcinkowski + - Warwick + - Chris + - Farid Jalilov + - Christiaan Wiesenekker + - Nicolas Pion + - Ariful Alam + - Florent Olivaud + - Foxprodev + - Eric Hertwig + - JakeFr + - Oliver Klee + - Niels Robin-Aubertin + - Simon Sargeant + - efeen + - Jan Christoph Beyer + - Muhammed Akbulut + - Nathanael d. Noblet + - Daniel Tiringer + - Rénald Casagraude (rcasagraude) + - Xesau + - Koray Zorluoglu + - Steeve Titeca (stiteca) + - Roy-Orbison + - Aaron Somi + - Elías (eliasfernandez) + - kshida + - Yasmany Cubela Medina (bitgandtter) + - Brian Graham (incognito) + - Michał Dąbrowski (defrag) + - Aryel Tupinamba (dfkimera) + - Hans Höchtl (hhoechtl) + - Jeremy Benoist + - Kevin Vergauwen (innocenzo) + - Alessio Baglio (ioalessio) + - Johannes Müller (johmue) + - Jordi Llonch (jordillonch) + - julien_tempo1 (julien_tempo1) + - Roman Igoshin (masterro) + - Nicholas Ruunu (nicholasruunu) + - Pierre Rebeilleau (pierrereb) + - Milos Colakovic (project2481) + - Raphael de Almeida (raphaeldealmeida) + - Mohammad Ali Sarbanha (sarbanha) + - Sergii Dolgushev (sergii-swds) + - Thomas Citharel (tcit) + - Alex Niedre + - evgkord + - Helmer Aaviksoo + - Roman Orlov + - Simon Ackermann + - Andreas Allacher + - VolCh + - Alexey Popkov + - Gijs Kunze + - Artyom Protaskin + - Steven Dubois + - Yurun + - ged15 + - Simon Asika + - Daan van Renterghem + - Raito Akehanareru (raito) + - Valmont Pehaut-Pietri (valmonzo) + - Bálint Szekeres + - amcastror + - Bram Van der Sype (brammm) + - Guile (guile) + - Mark Beech (jaybizzle) + - Julien Moulin (lizjulien) + - Mauro Foti (skler) + - Thibaut Arnoud (thibautarnoud) + - Yannick Warnier (ywarnier) + - Jörn Lang + - Kevin Decherf + - Paul LE CORRE + - Christian Weiske + - Maria Grazia Patteri + - dened + - muchafm + - Dmitry Korotovsky + - Michael van Tricht + - ReScO + - Tim Strehle + - Sébastien COURJEAN + - cay89 + - Sam Ward + - Hans N. Hjort + - Marko Vušak + - Walther Lalk + - Adam + - vltrof + - Ismo Vuorinen + - Markus Staab + - Valentin + - Gerard + - Sören Bernstein + - michael.kubovic + - devel + - Iain Cambridge + - Artem Lopata + - Viet Pham + - Alan Bondarchuk + - Pchol + - Benjamin Ellis + - Shamimul Alam + - Cyril HERRERA + - dropfen + - RAHUL K JHA + - Andrey Chernykh + - Edvinas Klovas - Drew Butler - - Alexey Berezuev - - pawel-lewtak - - Pierrick Charron - - Steve Müller - - omerida - - Andras Ratz - - andreabreu98 - - Marcus - - gechetspr - - brian978 - - Michael Schneider - - n-aleha - - Richard Čepas - - Talha Zekeriya Durmuş - - Anatol Belski - - Javier - - Alexis BOYER - - bch36 - - Kaipi Yann - - wiseguy1394 - - adam-mospan - - AUDUL - - Steve Hyde - - AbdelatifAitBara - - nerdgod - - Sam Williams - - Ettore Del Negro - - Guillaume Aveline - - Adrian Philipp - - James Michael DuPont - - Simone Ruggieri - - Markus Tacker + - Peter Breuls + - Chansig + - Kevin EMO + - Tischoi + - Sergii Dolgushev (serhey) + - divinity76 + - Amin Hosseini (aminh) + - vdauchy + - Andreas Hasenack + - J Bruni + - vlakoff + - Anthony Tenneriello + - thib92 + - Yiorgos Kalligeros + - Rudolf Ratusiński + - Bertalan Attila + - Arek Bochinski + - Rafael Tovar + - AmsTaFF (amstaff) + - Simon Müller (boscho) + - Yannick Bensacq (cibou) + - Cyrille Bourgois (cyrilleb) + - Damien Vauchel (damien_vauchel) + - Dmitrii Fedorenko (dmifedorenko) + - Frédéric G. Marand (fgm) + - Freek Van der Herten (freekmurze) + - Luca Genuzio (genuzio) + - Ioana Hazsda (ioana-hazsda) + - Jan Marek (janmarek) + - Mark de Haan (markdehaan) + - Maxime Corteel (mcorteel) + - Mathieu MARCHOIS (mmar) + - Nei Rauni Santos (nrauni) + - Geoffrey Monte (numerogeek) + - Martijn Boers (plebian) + - Plamen Mishev (pmishev) + - fabi + - Rares Vlaseanu (raresvla) + - Trevor N. Suarez (rican7) + - Clément Bertillon (skigun) + - Ahmed HANNACHI (tiecoders) + - Rein Baarsma (solidwebcode) + - tante kinast (tante) + - Stephen Lewis (tehanomalousone) + - Vincent LEFORT (vlefort) + - Andrew Marcinkevičius (ifdattic) + - Dan Patrick (mdpatrick) + - Ben Gamra Housseine (hbgamra) + - Darryl Hein (xmmedia) + - Wim Molenberghs (wimm) + - David Christmann + - Walid BOUGHDIRI (walidboughdiri) + - Marcel Berteler + - sdkawata + - Frederik Schmitt + - Peter van Dommelen + - Tim van Densen + - Andrzej + - tomasz-kusy + - Rémi Blaise + - Nicolas Séverin + - patrickmaynard + - Houssem + - Joel Marcey + - zolikonta + - Daniel Bartoníček + - Grégory Pelletier (ip512) + - natechicago + - Julien Pauli + - Juan Miguel Besada Vidal (soutlink) - Tomáš Votruba - - Kasperki - - dima-gr - - Daniel Strøm - - Tammy D - - Rodolfo Ruiz - - tsilefy - - Enrico - - Adrien Foulon - - Sylvain Just - - Ryan Rud - - Ondrej Slinták - - Jérémie Broutier - - vlechemin - - Brian Corrigan - - Ladislav Tánczos - - Brian Freytag - - Skorney - - Lucas Matte - - Success Go - - fmarchalemisys - - MGatner - - mieszko4 - - Steve Preston - - ibasaw - - koyolgecen - - Wojciech Skorodecki - - Kevin Frantz - - Neophy7e - - Evert Jan Hakvoort - - bokonet - - Arrilot - - andrey-tech - - David Ronchaud - - Chris McGehee - - Shaun Simmons - - Pierre-Louis LAUNAY - - Arseny Razin - - A. Pauly - - djama - - Benjamin Rosenberger - - Vladyslav Startsev - - Michael Gwynne - - Eduardo Conceição - - changmin.keum - - Jon Cave - - Sébastien HOUZE - - Abdulkadir N. A. - - Markus Klein - - Adam Klvač - - Bruno Nogueira Nascimento Wowk - - Tomanhez - - satalaondrej - - Matthias Dötsch - - jonmldr - - Nowfel2501 - - Yevgen Kovalienia - - Lebnik - - Shude - - RTUnreal - - Richard Hodgson - - Sven Fabricius + - Ross Motley (rossmotley) + - Cedric BERTOLINI (alsciende) + - Lyubomir Grozdanov (lubo13) + - Grayson Koonce + - Simone Fumagalli (hpatoio) + - Peter Dietrich (xosofox) + - Brandon Antonio Lorenzo + - Rafał Muszyński (rafmus90) + - Thierry Marianne + - Brieuc Thomas + - Ole Rößner (basster) + - Jonny Schmid (schmidjon) - Antonio Mansilla - - Ondřej Führer - - Bogdan - - Sema - - Ayke Halder - - Thorsten Hallwas - - Brian Freytag + - Johan + - Michael Simonson (mikes) + - Jordan de Laune (jdelaune) + - Michał Marcin Brzuchalski (brzuchal) + - César Suárez (csuarez) + - Thomas Dutrion (theocrite) + - Daniele Cesarini (ijanki) + - Silas Joisten (silasjoisten) + - uncaught + - Boris Medvedev + - Alexander Bauer (abauer) + - Nicolas ASSING (nicolasassing) + - Maksym Romanowski (maxromanovsky) + - Juan Luis (juanlugb) + - robin.de.croock + - Frankie Wittevrongel + - Ondřej Frei + - excelwebzone + - Martin Auswöger + - Vladimir Sadicov (xtech) + - Andrew Zhilin (zhil) + - Valentin Nazarov + - Guillaume Royer - Arend Hummeling - - Joseph FRANCLIN - - Marco Pfeiffer - - Alex Nostadt - - Michael Squires - - Egor Gorbachev - - Julian Krzefski - - Derek Stephen McLean - - PatrickRedStar - - Norman Soetbeer - - zorn - - Yuriy Potemkin - - Emilie Lorenzo - - prudhomme victor - - enomotodev - - Vincent - - Benjamin Long - - Fabio Panaccione - - Kévin Gonella - - Ben Miller - - Peter Gribanov - - Matteo Galli - - Bart Ruysseveldt - - Ash014 - - Loenix - - kwiateusz - - Ilya Bulakh - - David Soria Parra - - Simon Frost - - Sergiy Sokolenko - - Cantepie - - detinkin - - Ahmed Abdulrahman - - dinitrol - - Penny Leach - - Kevin Mian Kraiker - - Yurii K - - Richard Trebichavský - - Rich Sage - - g123456789l - - Mark Ogilvie - - Jonathan Vollebregt - - oscartv - - DanSync - - Peter Zwosta - - Michal Čihař - - parhs - - Harry Wiseman - - Emilien Escalle - - jwaguet - - Diego Campoy - - Oncle Tom - - Roland Franssen :) - - Sam Anthony - - Christian Stocker - - Oussama Elgoumri - - Gert de Pagter - - David Lima - - Steve Marvell - - Dawid Nowak - - Lesnykh Ilia - - Shyim - sabruss - - darnel - - Nicolas - - Sergio Santoro - - tirnanog06 - - Andrejs Leonovs - - llupa - - Alfonso Fernández García - - phc - - Дмитрий Пацура - - Signor Pedro - - RFreij - - Matthias Larisch - - Maxime P - - Sean Templeton - - Willem Mouwen - - db306 - - Bohdan Pliachenko - - Dr. Gianluigi "Zane" Zanettini - - Michaël VEROUX - - Julia - - Lin Lu - - arduanov - - sualko - - Marc Bennewitz - - Fabien - - Martin Komischke - - Yendric - - ADmad - - Hugo Posnic - - Nicolas Roudaire - - Marc Jauvin - - Matthias Meyer - - Abdouni Karim (abdounikarim) - - Temuri Takalandze (abgeo) - - Bernard van der Esch (adeptofvoltron) - - Andreas Forsblom (aforsblo) - - Aleksejs Kovalovs (aleksejs1) - - Alex Olmos (alexolmos) - - Cedric BERTOLINI (alsciende) - - Robin Kanters (anddarerobin) - - Antoine (antoinela_adveris) - - Juan Ases García (ases) - - Siragusa (asiragusa) - - Daniel Basten (axhm3a) - - Albert Bakker (babbert) - - Benedict Massolle (bemas) - - Gerard Berengue Llobera (bere) - - Ronny (big-r) - - Bernd Matzner (bmatzner) - - Vladimir Vasilev (bobahvas) - - Anton (bonio) - - Bram Tweedegolf (bram_tweedegolf) - - Brandon Kelly (brandonkelly) - - Choong Wei Tjeng (choonge) - - Bermon Clément (chou666) - - Chris Shennan (chrisshennan) - - Citia (citia) - - Kousuke Ebihara (co3k) - - Loïc Vernet (coil) - - Christoph Vincent Schaefer (cvschaefer) - - Kamil Piwowarski (cyklista) - - Damon Jones (damon__jones) - - David Courtey (david-crty) - - David Gorges (davidgorges) - - Alexandre Fiocre (demos77) - - Łukasz Giza (destroyer) - - Daniel Londero (dlondero) - - Dušan Kasan (dudo1904) - - Sebastian Landwehr (dword123) - - Adel ELHAIBA (eadel) - - Damián Nohales (eagleoneraptor) - - Elliot Anderson (elliot) - - Erwan Nader (ernadoo) - - Fabien D. (fabd) - - Carsten Eilers (fnc) - - Sorin Gitlan (forapathy) - - Fraller Balázs (fracsi) - - Lesueurs Frédéric (fredlesueurs) - - Yohan Giarelli (frequence-web) - - Gerry Vandermaesen (gerryvdm) - - Arash Tabrizian (ghost098) - - Greg Szczotka (greg606) - - Ian Littman (iansltx) - - Nathan DIdier (icz) - - Vladislav Krupenkin (ideea) - - Peter Orosz (ill_logical) - - Ilia Lazarev (ilzrv) - - Imangazaliev Muhammad (imangazaliev) - - wesign (inscrutable01) + - Knallcharge + - gndk + - Markus Tacker + - Fabian Steiner (fabstei) - Arkadiusz Kondas (itcraftsmanpl) - - j0k (j0k) - - joris de wit (jdewit) - - JG (jege) - - Jérémy CROMBEZ (jeremy) - - Jose Manuel Gonzalez (jgonzalez) - - Joachim Krempel (jkrempel) - - Jorge Maiden (jorgemaiden) - - Joshua Behrens (joshuabehrens) - - Joao Paulo V Martins (jpjoao) - - Justin Rainbow (jrainbow) - - Juan Luis (juanlugb) - - JuntaTom (juntatom) - - Julien Manganne (juuuuuu) - - Ismail Faizi (kanafghan) - - Karolis Daužickas (kdauzickas) - - Kérian MONTES-MORIN (kerianmm) - - Sébastien Armand (khepin) - - Pierre-Chanel Gauthier (kmecnin) - - Krzysztof Menżyk (krymen) - - Kenjy Thiébault (kthiebault) - - samuel laulhau (lalop) - - Laurent Bachelier (laurentb) - - Luís Cobucci (lcobucci) - - Jérémy (libertjeremy) - - Mehdi Achour (machour) - - Mamikon Arakelyan (mamikon) - - Mark Schmale (masch) - - Matt Ketmo (mattketmo) - - Moritz Borgmann (mborgmann) - - Matt Drollette (mdrollette) - - Adam Monsen (meonkeys) - - Mike Milano (mmilano) - - Guillaume Lajarige (molkobain) - - Diego Aguiar (mollokhan) - - Steffen Persch (n3o77) - - Ala Eddine Khefifi (nayzo) - - emilienbouard (neime) - - Nicholas Byfleet (nickbyfleet) - - Nicolas Bondoux (nsbx) - - Cedric Kastner (nurtext) - - ollie harridge (ollietb) - - Aurimas Rimkus (patrikas) - - Pawel Szczepanek (pauluz) - - Philippe Degeeter (pdegeeter) - - PLAZANET Pierre (pedrotroller) - - Christian López Espínola (penyaskito) - - Petr Jaroš (petajaros) - - Pavel Golovin (pgolovin) - - Philipp Hoffmann (philipphoffmann) - - Alex Carol (picard89) - - Daniel Perez Pinazo (pitiflautico) - - Igor Tarasov (polosatus) - - Maksym Pustynnikov (pustynnikov) - - Ralf Kühnel (ralfkuehnel) - - Seyedramin Banihashemi (ramin) - - Ramazan APAYDIN (rapaydin) - - Babichev Maxim (rez1dent3) - - scourgen hung (scourgen) - - Sebastian Busch (sebu) - - Sergey Stavichenko (sergey_stavichenko) - - André Filipe Gonçalves Neves (seven) - - Bruno Ziegler (sfcoder) - - Ángel Guzmán Maeso (shakaran) - - Andrea Giuliano (shark) - - Şəhriyar İmanov (shehriyari) + - Alexander Kurilo (kamazee) + - Lars Ambrosius Wallenborn (larsborn) + - Malte Wunsch (maltewunsch) + - Matteo Giachino (matteosister) - Thomas Baumgartner (shoplifter) - - Schuyler Jager (sjager) + - Vladimir Chernyshev (volch) + - Oz (import) + - Felix Eymonot (hyanda) + - Stanislau Kviatkouski (7-zete-7) - Christopher Georg (sky-chris) - - Volker (skydiablo) - - Julien Sanchez (sumbobyboys) - - Ron Gähler (t-ronx) - - Guillermo Gisinger (t3chn0r) - - Tomáš Korec (tomkorec) - - Tom Newby (tomnewbyau) - - Andrew Clark (tqt_andrew_clark) - - Aaron Piotrowski (trowski) - - David Lumaye (tux1124) - - Roman Tymoshyk (tymoshyk) - - Moritz Kraft (userfriendly) - - Víctor Mateo (victormateo) - - Vincent MOULENE (vints24) - - Verlhac Gaëtan (viviengaetan) - - David Grüner (vworldat) - - Eugene Babushkin (warl) - - Wouter Sioen (wouter_sioen) - - Xavier Amado (xamado) - - Jesper Søndergaard Pedersen (zerrvox) - - Florent Cailhol - - szymek - - Ryan Linnit - - Konrad - - Kovacs Nicolas - - eminjk - - craigmarvelley - - Stano Turza - - Antoine Leblanc - - drublic - - Andre Johnson - - MaPePeR - - Andreas Streichardt - - Alexandre Segura - - Marco Pfeiffer - - Vivien - - Pascal Hofmann - - david-binda - - smokeybear87 - - Gustavo Adrian - - damaya - - Kevin Weber - - Alexandru Năstase - - Carl Julian Sauter - - Dionysis Arvanitis - - Sergey Fedotov - - Konstantin Scheumann - - Josef Hlavatý - - Michael - - fh-github@fholzhauer.de - - rogamoore - - AbdElKader Bouadjadja - - ddegentesh - - DSeemiller - - Jan Emrich - - Anne-Julia Seitz - - mindaugasvcs - - Mark Topper - - Romain - - Xavier REN - - Kevin Meijer - - Ignacio Alveal - - max - - Alexander Bauer (abauer) - - Ahmad Mayahi (ahmadmayahi) - - Mohamed Karnichi (amiral) - - Andrew Carter (andrewcarteruk) - - Adam Elsodaney (archfizz) - - Gregório Bonfante Borba (bonfante) - - Bogdan Rancichi (devck) - - Daniel Kolvik (dkvk) - - Marc Lemay (flug) - - Gabriel Solomon (gabrielsolomon) - - Courcier Marvin (helyakin) - - Henne Van Och (hennevo) - - Jeroen De Dauw (jeroendedauw) - - Muharrem Demirci (mdemirci) - - Evgeny Z (meze) - - Aleksandar Dimitrov (netbull) - - Pierre-Henry Soria 🌴 (pierrehenry) - - Pierre Geyer (ptheg) + - tamcy + - Yohann Tilotti + - Muhammad Aakash + - Anthony Moutte + - Adoni Pavlakis (adoni) + - Nicolas Le Goff (nlegoff) + - Tero Alén (tero) + - Daniel Londero (dlondero) + - Ryan Rogers + - Stephen + - aim8604 + - ZiYao54 + - Eric Stern + - Guillaume BRETOU (guiguiboy) + - Artiom + - Bruno BOUTAREL + - Jakub Simon + - Bernat Llibre Martín (bernatllibre) + - Zayan Goripov + - downace + - Robin Duval (robin-duval) + - Ivo + - pf + - elattariyassine + - Joris Garonian (grifx) + - Tito Miguel Costa (titomiguelcosta) + - goohib + - andrey-tech + - dinitrol + - Jérémy CROMBEZ (jeremy) + - mlievertz + - Benjamin Paap (benjaminpaap) + - Uladzimir Tsykun + - Fred Cox + - Ksaveras Šakys (xawiers) + - Lin Clark + - RevZer0 (rav) + - Yura Uvarov (zim32) + - Dan Finnie + - Nerijus Arlauskas (nercury) + - Clément + - Philipp Kretzschmar + - Jairo Pastor + - rtek + - Kévin Gomez (kevin) + - Sébastien HOUZÉ + - BrokenSourceCode + - Robert-Jan de Dreu + - simbera + - Peter Schultz + - Wissame MEKHILEF + - Mihai Stancu + - shreypuranik + - Koalabaerchen + - alex + - gedrox + - Pedro Magalhães (pmmaga) + - Ari Pringle (apringle) + - Dan Ordille (dordille) + - Juan M Martínez + - Matt Fields + - Lajos Veres (vlajos) + - toxxxa + - Kai Eichinger + - Antonio Angelino + - CarolienBEER + - Tammy D + - Kevin Frantz + - bokonet + - Sébastien Armand (khepin) - Richard Henkenjohann (richardhj) - - Thomas BERTRAND (sevrahk) - - Vladislav (simpson) - - Marin Bînzari (spartakusmd) - - Stefanos Psarras (stefanos) - - Matej Žilák (teo_sk) - - Gary Houbre (thegarious) - - Vladislav Vlastovskiy (vlastv) - - RENAUDIN Xavier (xorrox) - - Yannick Vanhaeren (yvh) - - Zan Baldwin (zanderbaldwin) + - 蝦米 + - klemens + - Lane Shukhov + - Dennis Jaschinski (d.jaschinski) + - Martin Eckhardt + - André Matthies + - ttomor + - Gavin (gavin-markup) + - Evgeny Ruban + - Florian Bogey + - Soha Jin + - Alexander Zogheb + - Rich Sage + - sualko + - koyolgecen + - James Mallison + - BT643 + - M.Wiesner + - Erdal G + - Daniel Siepmann + - Alaa AttyaMohamed (alaaattya) + - atmosf3ar + - aziz benmallouk (aziz403) + - Rob Meijer (robmeijer) + - Bruno Ferme Gasparin (bfgasparin) + - silver-dima + - Ldiro + - Nick Winfield + - Raphaël Geffroy + - Asma Drissi (adrissi) + - Egor Ushakov (erop) + - Janusz Slota (janusz.slota) + - Szymon Skowroński (skowi) + - Thomas Le Duc (viper) + - Artur Butov (vuras) + - Neal Brooks (nealio82) + - Fabian Spillner (fspillner) + - SirRFI + - Jérôme Poskin (moinax) + - z38 + - lacatoire + - Bill Israel + - Armen Mkrtchyan (iamtankist) + - RisingSunLight + - unknown + - Sam Korn + - Surfoo (surfoo) + - dcramble + - Anthony Rey (sydney_o9) + - Daniel Felix (danielfellix) + - Janosch Oltmanns (janosch_oltmanns) + - Christian + - Giuseppe Attardi + - Walter Nuñez + - Bart van Raaij (bartvanraaij) + - David Paz (davidmpaz) + - Markus Tacker + - Kim Wüstkamp (kimwuestkamp) + - tchap + - Benjamin Bourot + - Chris McMacken (chrism) + - Benjamin Lazarecki (benjaminlazarecki) + - matt smith (dr-matt-smith2) + - Kane Menicou (kane-menicou) + - Stéphane Paul BENTZ (spbentz) + - KaroDidi + - CJDennis + - Olivier Toussaint (cinquante) + - Raul C + - Cristi Contiu (cristi-contiu) + - Tim + - Marcel Korpel + - Yaroslav Yaremenko + - Justin Liiper (liiper) + - Al-Saleh KEITA + - Dan Michael O. Heggø (danmichaelo) + - Laurens Laman (laulaman) + - Joe Hans Robles Martínez (joebuntu) + - Florian Körner (koernerws) + - Agustín Pacheco Di Santi + - d.syph.3r + - Hyunmin Kim (kigguhholic) + - Alexis Urien (axi35) + - Marek Bartoš + - Markus Tacker + - Thomas P + - Jeroen + - Aymeric Mayeux (aymdev) + - Kamil Pešek (kamil_pesek) + - Nicolas Clavaud (nclavaud) + - Aaron Valandra + - Myystigri + - Guillaume Sarramegna + - Kristof (jockri) + - Jérémy Crapet + - Ahmed Lebbada (sidux) + - Alexis Lefebvre + - Alex Theobold + - Abdellah EL GHAILANI (aelghailani) + - Benjamin D. (benito103e) + - Mark Badolato (mbadolato) + - Tsimafei Charniauski (varloc2000) + - Sherin Bloemendaal + - laurent negre + - Beno!t POLASZEK + - Mario Martinez (chichibek) + - Florian Bastien (fbastien) + - Maik Penz + - Brooks Van Buren (brooksvb) + - Axel K. + - Ivan Yivoff + - wouthoekstra + - Paul Waring + - Brice Lalu (bricelalu) + - Alexandre Castelain (calex_92) + - Rafał Mnich (rafalmnich-msales) + - Andrei Karpilin (karpilin) + - Julien Dephix + - Mathieu + - Jade Xau + - Thomas Berends + - Nils Freigang (pueppiblue) + - Juan Manuel Fernandez (juanmf) + - Ben Glassman (bglassman) + - unknown + - Pierre Maraître (balamung) + - Kolyunya (kolyunya) + - Daniel Kesselberg (kesselb) + - MarcomTeam + - gitomato + - Thibault Pelloquin (thibault_pelloquin) + - Heaven31415 + - Pavel Máca + - Michael Sheakoski + - Patrick Bielen + - Emir Beganović (emirb) + - Tim Stamp + - Daniel Parejo Muñoz (xdaizu) + - Florian-B + - Guillaume Rossignol + - Marcin Sekalski + - Wouter J + - Kai Eichinger (kai_eichinger) + - Matthew Loberg (mloberg) + - xuni + - timothymctim + - tuanalumi + - ayacoo + - Kevin Lot + - Andrea Cristaudo + - Romain + - Jochem Klaver + - Aalaap Ghag (aalaap) + - Eric Poe (ericpoe) + - Giancarlos Salas (giansalex) + - Gauthier Gilles + - Julien Ferchaud (guns17) + - Pedro Junior (vjnrv) + - Max R (maxr) + - xamgreen + - Igor + - Michal Zuber + - Lyrkan + - Maxime Cornet (elysion) + - Arvydas K + - Chris Thompson (toot) + - Carl Schwan + - Vince (zhbzhb) + - Hamza Hanafi + - Bogdan Olteanu + - Nurlan Alekberov + - Jérôme Nadaud + - entering + - OИUЯd da silva + - Clément MICHELET (chiendelune) + - Erison silva (eerison) + - Sarim Khan (gittu) + - Jakub Szcześniak (jakubszczesniak) + - JohnyProkie (john_prokie) + - Krzysztof Daniel (krzysdan) + - Mitchel (mitch) + - Pierre Joube (pierrejoube) + - Zairig Imad + - Romain Biard (rbiard) + - Nik Spijkerman + - Luka Žitnik + - Eugene Wolfson + - Danielle Suurlant (dsuurlant) + - Julien Deniau (jdeniau) + - van truong PHAN (vantruongphan) + - Alex Luneburg + - MohamedElKadaoui + - iqfoundry + - Lauri + - Thomas Ploch + - Franklin LIA + - autiquet axel + - Florentin Garnier + - Alex Wybraniec + - Paweł Farys + - Carlton Dickson (carltondickson) + - Christopher Hoult (choult) + - Clemens Krack (ckrack) + - George Pogosyan (gp) + - Joshua (suabahasa) + - Jean-Baptiste Delhommeau (jbdelhommeau) + - Kristian Zondervan (krizon) + - Mathias Geat (maffibk) + - Alex Brims (outspaced) + - Joel Doyle (oylex) + - Pau Oliveras (poliveras) + - Shane Archer (sarcher) + - Leanna Pelham (leannapelham) + - Stefan Doorn (stefandoorn) + - M E (ttc) + - Christophe Deliens (cdeliens) + - Tony Tran (tony-tran) + - Alden Weddleton (wnedla) + - Patryk Miedziaszczyk + - Michael Lenahan + - Giacomo Moscardini + - Kris + - Dustin Meiner + - Arc Tod + - Max Schindler (chucky2305) + - Kai (kai_dederichs) + - SamanShafigh + - Andrii Mishchenko (krlove) + - KULDIP PIPALIYA (kuldipem) + - Taiwo A (tiwiex) + - Tobias Olry (tolry) + - Maxime Douailin + - Chris Taylor + - Andy Dawson + - Jason Grimes + - jonasarts + - Salah MEHARGA + - Marvin Hinz + - Jacek Jędrzejewski + - chapterjason + - mohamed + - rodmar35 + - Krzysztof Lament + - Euge Starr + - Steve Nebes + - jms85 + - M.Eng. René Schwarz + - Shawn Dellysse + - Steve + - Rico Neitzel + - Alessio Pierobon (alepsys) + - Andrey Bolonin + - robert Parker + - ampt . (ampt) + - Philippe Mine (dispositif) + - Favian Ioel Poputa (favianioel) + - Fernando Aguirre Larios (ingaguirrel) + - Javi H. Gil (javibilbo) + - Jean-Marie Lamodière (jmlamo) + - XitasoChris + - kenjis (kenjis) + - Kevin Archer (kevarch) + - Žilvinas Kuusas (kuusas) + - Mostefa Medjahed (mostefa) + - Andrianovah nirina randriamiamina (novah) + - Nicolas Potier (npotier) + - Ejamine + - moon-watcher + - Paweł Skotnicki (pskt) + - Andrey (quiss) + - Robert Saylor (rsaylor) + - Rubén Rubio Barrera (rubenrubiob) + - Rick van Laarhoven (rvanlaarhoven) + - Therage Kevin + - Saad Tazi (saadtazi) + - Sasha Matejic (smatejic) + - Yopai + - Souhail (souhail_5) + - Valentin Ferriere (choomz) + - JakeFr + - Rémi T'JAMPENS (tjamps) + - venu (venu) + - Nicolas Dievart (youri) + - Zaid Rashwani (zrashwani) + - authentictech + - Jordan Lev + - James (acidjames) + - Pierre Galvez (shafan_dev) + - Ulrich Völkel (udev) + - Nebojša Kamber + - Stepan Mednikov + - Uri Goldshtein + - Vyacheslav Pavlov + - Pierre de Soos + - Johnny Peck + - Mario Young + - Cangit + - TrueGit + - Tim Kuijsten + - Dennis Benkert + - Nicola Pietroluongo + - Charcosset Johnny + - Hmache Abdellah + - ABRAHAM Morgan + - Lucas Mlsna + - RickieL + - Xavier Laviron + - Severin J + - Julien (mewt) + - Alexander O'Neill + - Jürgen + - Bruno Vitorino + - Daniel Werner (powerdan) + - Lukáš Brzák (rapemer) + - adursun + - Alihasana SHAIKALAUDDEEN + - Darmen Amanbayev + - Leonel Machava + - javaDeveloperKid + - Syedi Hasan + - Tom Nguyen + - Yngve Høiseth + - dawidpierzchalski + - Steve Wasiura + - Muhammad Nasir Rahimi + - Rick Pastoor + - Gun5m0k3 + - Gilles Taupenas + - Brian Gallagher + - MarvinBlstrli + - Marichez Pierre (chtipepere) + - Danny Kopping (dannykopping) + - Krzysztof Lechowski (kshishkin) + - Andras Ratz (ghostika) + - Michael Sivolobov (astronomer) + - Quentin Stoeckel (chteuchteu) + - Rafael Gil (cybervoid) + - Cyril VERLOOP (cyrilverloop) + - Ivan Kosheliev (dfyz) + - Duane Gran (duanegran) + - Thomas Decaux (ebuildy) + - Fred Jiles (fredjiles) + - Glen Jaguin (gl3n) + - Joshua Dickerson (groundup) + - Julio (gugli100) + - Dan Finnie + - Yassine Fikri (yassinefikri) + - Hector Hurtarte (hectorh30) + - Oliver Forral (intrepion) + - Jack Delin (jackdelin) + - Jean-Luc MATHIEU (jls2933) + - Josh Taylor (josher) + - Kevin Robatel (kevinrob) + - Keefe Kwan (kkwan) + - Piotr Gołębiewski (loostro) + - Maxime Morlet (maxicom) + - Ana Cicconi + - Mohamed Ettaki TALBI (takman) + - Michał Kurcewicz (mkurc1) + - nencho nencho (nencho) + - pbijl (pbijl) + - Patrick Maynard + - rahul (rahul) + - bouffard (shinmen33) + - Kevin Carmody (skinofstars) + - Tomasz Tybulewicz (tybulewicz) + - Vlad Ghita (vghita) + - Ahmed El Moden + - Unlikenesses + - Ousmane NDIAYE + - Erlang Parasu (erlangparasu) + - Pieter Oliver + - Viacheslav Demianov (sdem) + - David ALLIX (weba2lix) + - Carlos Granados + - kirill-oficerov + - aliber4079 + - ptrm04 + - Jeroen Deviaene + - Marc Verney + - Goran Grbic (tpojka) + - Marcin Sękalski (senkal) + - Frédéric Planté + - Alexandr Podgorbunschih (apodgorbunschih) + - Thomas Kappel + - Charles EDOU NZE + - Daichi Kamemoto (yudoufu) + - Oliver Stark (oliver.stark) + - gnito-org + - Marc Verney + - alexmart + - Daniël Brekelmans + - Loïc Salanon + - Mathias STRASSER + - Navid Salehi (nvdsalehi) + - armin-github + - Jerome Gangneux + - Denis Brumann + - Daryl Gubler (dev88) + - Dorian Sarnowski (dorian) + - Viktor Linkin (adrenalinkin) + - Stephen Ostrow (isleshocky77) + - Thijs Feryn + - Ionut Enache + - Conrad Pankoff + - Stefan hr Berder + - Micheal Cottingham (micheal) + - Dylan Delobel (dylandelobel) + - Shiraz (zpine) + - Edgar Brunet + - Jeff Zohrab + - CvekCoding + - Philippe Milot + - Gilles Gauthier + - Eöras + - lacpandore + - Emilio de la Torre (emiliodelatorrea) + - Terje Bråten + - Marcin Muszynski + - Robin Delbaere (rdelbaere) + - Albert Moreno + - Moroine Bentefrit + - Romain Petit + - Fabien Bourigault + - Daniele D'Angeli (erlangb) + - mervinmcdougall + - Olivier Acmos (olivier_acmos) + - mccullagh + - technetium + - Dimitri Labouesse + - Tyler King + - Piotr Grabski-Gradziński (piotrgradzinski) + - Iqbal Malik (iqbal_malik89) + - Lucas CHERIFI (kasifi) + - hidde.wieringa + - Peter Bottenberg + - Sofien NAAS + - Freerich Bäthge (freerich) + - Lopton + - MarkPedron + - JhonnyL + - grelu + - Russell Flynn (rooster) + - Malte Blättermann + - Lander Vanderstraeten + - Florian Moser + - Éric + - Arnaud Lejosne + - larsborn + - Steve Clay (mrclay) + - Pierre Pélisset (ppelisset) + - Tarjei Huse (symfony_cloud) + - Damien Fayet + - Lucas Mlsna + - Philippe Gamache (philippegamache) + - Cyanat + - Terje Bråten + - Vincent Chareunphol (devoji) + - Francisco Corrales Morales + - Florian CAVASIN + - Nic Wortel (nicwortel) + - Masaharu Suizu + - Luděk Uiberlay (ne0) + - Dominic Luechinger + - jsarracco + - Shevelev Vladimir (shevelev_vladimir) + - LiVsI + - Jalen Muller (jalenwasjere) + - Marc Straube + - Louis-Arnaud + - Adam Prancz (praad) + - Hubert Moutot (youbs) + - Jan Grubenbecher + - Younes OUASSI (youassi) + - kolossa + - eric fernance (ericrobert) + - Alexandre Balmes (pocky) + - Aaron Baker + - SquareInnov + - dellamowica + - Caliendo Julien + - Damien Tournoud + - Eike Send + - Robin Brisa + - Kevin Boyd + - Raistlfiren + - Daniel Klein + - Bruce Phillips + - LICKEL Gaetan (cilaginept) + - Jacek (opcode) + - Baptiste Pizzighini (bpizzi) + - David D. (comxd) + - Tristan Pouliquen (tristanpouliquen) + - PululuK + - Jens Hassler + - Hylke + - Simon Schubert (simon-schubert) + - avanwieringen + - j00seph + - Ivan Nemets + - Benjamin Laugueux + - sgautier + - Kevin Mark + - Marijn Huizendveld + - Denis Brumann + - Alexandre GESLIN (rednaxe) + - Grzegorz Dembowski (gdembowski) + - Ramzi Abdelaziz (ramzi_a) + - PéCé + - Jess + - Matt Janssen + - Camille Jouan (ca-jou) + - Kerrial (kez) + - Lambert Beekhuis (lambertb) + - Nassim LOUNADI + - pamuche + - zuhair-naqvi + - Miguel Vilata (adder) + - Vladislav Lezhnev (livsi) + - Mark Smith (zfce) + - Michel Valdrighi (michelv) + - Martin Czerwinski + - Clayton + - Wojciech Sznapka + - Ludovic REUS + - David Desberg + - Adam Mikolaj (mausino) + - harcod + - cancelledbit + - Claude Ramseyer (phenix789) + - Gaurish Sharma + - Prathap + - sblaut + - Kirill Kotov + - BorodinDemid + - iamdto (iamdto) + - David Lumaye + - Pavel Shirmanov (genzo) + - Rodrigo Capilé (rcapile) + - Quentin Fahrner (renrhaf) + - James Isaac + - Pedro Piedade + - Edym Komlan BEDY (youngmustes) + - Xbird + - Milan Pavkovic + - Jonczyk + - Mbechezi Mlanawo + - Florimond Manca + - Ladislav Kubes + - bpiepiora + - Robert Brian Gottier + - Susheel Thapa + - Андрей + - Vincent Brouté + - Hugo Clergue + - Timo Tewes + - Dries Vints + - Piotr Stankowski + - Oliver Kossin + - Robert + - Alan Farquharson + - Bill Surgenor + - Pierre Arnissolle (arnissolle) + - Szilágyi Károly Bálint + - 6e0d0a + - Terence Eden + - Peter + - Mathias STRASSER + - Inori + - Artur + - ismail mezrani (imezrani) + - Luca Suriano (lucas05) + - michael schouman (metalmini) + - Hideki Okajima (okazy) + - Ronan Pozzi (treenity) + - Jeremiah Dodds + - Fabian Becker + - Tim Herlaud + - Michael Witten (micwit) + - r-ant-2468 + - Prisacari Dmitrii + - Stephen Clouse + - fguimier + - Mykola Martynov (mykola) + - Timo Haberkern (thaberkern) + - Damien DE SOUSA (dades) + - Valyaev Ilya (rumours86) + - Dan Barrett (yesdevnull) + - Robin C + - Wouter + - Mathieu Capdeville + - Florian VANHECKE + - Zombaya + - Tim Jabs + - JT Smith + - Rudy Onfroy + - Patrick PawseyVale + - Michaël Dieudonné + - Ilya Bakhlin + - analogic + - lucchese-pd + - Philippe Villiers + - LavaSlider + - Aikaterine Tsiboukas + - New To Vaux + - Guillermo Quinteros (guquinteros) + - Hex Titan (hextitan) + - Norio Suzuki (suzuki) + - Michael COULLERET (20uf) + - Tristan LE GACQUE (tristanlegacque) + - Jérémy Halin + - Scott + - fishbone1 + - lajosthiel + - pgorod + - E Ciotti + - Jeroen + - elescot + - vihuarar + - Tom Troyer + - Sébastien FUCHS + - Vilius Grigaliūnas + - Chloé B. + - Manuel Andreo Garcia + - cirrosol + - matthieudelmas + - Ahmed Abdou (ahmedaraby) + - Calin Pristavu (calinpristavu) + - Hatem Ben (hatemben) + - Robin Cawser (robcaw) + - Jorisros (jorisros) + - Michael Dwyer (kalifg) + - Mohamed YOUNES (medunes) + - Manuele Menozzi (mmenozzi) + - Robert Went (robwent) + - Greg (kl3sk) + - scottwarren + - Michael Klein (monbro) + - Christoph Wieseke + - Przemek Maszczynski + - Sam Hudson + - piet + - Petar Petković + - stormoPL + - Bartosz Tomczak + - A goazil + - Felix Stein + - Wojciech Kania + - Ian Gilfillan + - sakul95 + - R1n0x + - Stéphane P + - rogamoore + - Jorge Sepulveda + - Lauri + - Simon Appelt + - broiniac + - Peter Hauke + - Fabian Freiburg + - Léo PLANUS + - Hari K T (harikt) + - Michel Chowanski (migo) + - M#3 + - ymc-sise + - DKravtsov + - Alexandr Kalenyuk + - Andreas Schönefeldt + - Sorin Dumitrescu (sfdumi) + - artf + - Alireza Rahmani Khalili (alireza_rahmani) + - Maxim (big-shark) + - Dirk Luijk (dirkluijk) + - Adam Lee Conlin (hades200082) + - Petru Szemereczki (hktr92) + - Jan Heller (jahller) + - Tobias Berge + - Jérémie Samson (jsamson) + - Pascal de Vink (pascaldevink) + - A S M Sadiqul Islam (sadiq) + - Emil Santi (emilius) + - Darien + - Cédric Spalvieri (skwi) + - Damien Chedan (tcheud) + - Valter Carneiro da Silva Junior (valterjrdev) + - Gabriel Birke (chiborg) + - BETARI Amine (amine_ezpublish) + - Tyler Sommer (veonik) + - chance garcia + - Antonio de la Vega + - Archie Vasyatkin + - Brian + - Ben Thomas + - Grégory Quatannens (gscorpio) + - Corentin + - Jan Klan (janklan) + - Jonathan + - Peter Gasser + - Jorick + - Jamal Youssefi + - Volen Davidov + - CaDJoU + - Mohameth + - Dilantha Nanayakkara + - wazz42 + - Brendan + - Massimo Giagnoni (mgiagnoni) + - Michael Phillips + - Brandon Mueller (fatmuemoo) + - LEFLOCH Jean-François (katsenkatorz) + - Luuk Scholten (lscholten) + - Matt Trask (matthewtrask) + - Paul Rijke (parijke) + - Anthony FACHAUX + - Paul Ferrett (paulf) + - Ronan Guilloux (ronan) + - David Ward (roverwolf) + - helmi dridi + - Marco Woehr + - Ali Sunjaya + - iarro + - Clément Barbaza + - Alexander Diebler + - Tom Egan + - Peter + - Dean Clatworthy + - Zoltan Toth-Czifra + - Juan Riquelme + - Mike Zukowsky + - Quentin Boulard + - vmarquez + - Talita Kocjan Zager (paxyknox) + - Sander Bol + - Son Tung PHAM + - Volker Thiel + - Raggok + - Benoît + - marco-pm + - VladZernov + - Julien RAVIA + - Robert Nagy + - Angelo Melonas (angelomelonas) + - nasaralla + - Rosemary Orchard + - Bruno Baguette (tournesol) + - Jean Pasdeloup + - Fabrice GARES (fabrice_g) + - Oliver Kossin + - Ignacio Aguirre + - German Bortoli (germanaz0) + - Patrik Csak + - Julien BENOIT + - Jason Aller (jraller) + - Ka (Karim Cassam Chenaï) + - e-weimann + - Greg Somers + - Andrej Rypo + - Matthias Noback (mnoback) + - heddi.nabbisen + - Marius-Liviu Balan (liv_romania) + - Brent Shaffer (bshaffer) + - Exalyon + - Maciej Łebkowski (mlebkowski) + - Javad Adib + - Jonas Wouters + - Lee Jorgensen (profmoriarty) + - Julien Gidel + - Ivan Gantsev + - Richard Perez (riperez) + - Antonio Spinelli + - Ross Deane (rossdeane) + - Pavel Jurecka + - Joel Clermont (jclermont) + - Brandin Chiu + - Sébastien Rogier (srogier) + - Arnaud Pflieger + - Roy Templeman + - Tobias Schmidt (tobias-schmidt) + - ehibes + - Jean-Philippe Dépigny + - Christian Weyand (weyandch) + - Romaxx + - I. Fournier + - Daan van Renterghem + - Alex Coventry + - Ali Yousefi (aliyousefi) + - lbraconnier2 + - ghertko + - Francis Hilaire + - vgmaarten + - Godfrey Laswai + - Stefan Topfstedt + - Nathan Vonnahme + - Quentin Brunet + - Robert Freigang (robertfausk) + - faissaloux + - oyerli + - Guillaume Ponty + - Jan Pieper + - Chris Johnson + - Tommi + - b0nd0 + - andybeak + - Pierre-Jean Leger + - vindby23 + - Damien + - Florian Blond (fblond) + - Christophe Willemsen (kwattro) + - guidokritz + - sofany + - FindAPattern + - Tom Haskins-Vaughan + - Kevin R + - Lance Bailey + - Dorozhko Anton + - Jonathan Clark + - Giulio Lastra + - Ed Poulain + - wiese + - Nietono + - Mahdi Maghrooni + - Vimal Gorasiya + - Baptiste Langlade + - Gasmi Mohamed (mohamed_gasmi) + - Angelo Galleja (ga.n) + - TavoNiievez + - Michele Carino + - Gustavo Henrique Mascarenhas Machado + - jfhovinne + - Thomas from api.video + - guiditoito + - Francois CONTE + - Danny van Wijk (dannyvw) + - Rick Ogden + - Tomáš Tibenský + - Ivan Ternovtsiy + - Thomas Lemaire + - Adamo Crespi + - Christopher Vrooman + - de l'Hamaide + - xelan + - Henrik Christensen + - João Paulo Vieira da Silva + - rayrigam + - ipatiev + - Xavier Coureau + - George Zankevich + - David Frerich + - Kris + - Linas Merkevicius + - Peter Majmesku + - srich387 + - Giuseppe Petraroli + - IamBeginnerC + - Yassine Hadj messaoud + - Oliver THEBAULT + - Arnaud + - Thomas Talbot + - Aurélien Thieriot + - abarke + - Benjamin Dos Santos + - Christopher Cardea + - ackerman + - RiffFred + - Idziak + - Krzysztof Nizioł + - alex00ds + - Michaël Mordefroy + - cvdwel + - Rafael Torres + - Ruben Petrosjan + - Filip Telążka + - Edward Kim + - Markus Mauksch + - Marko Mijailovic + - Théophile Helleboid - chtitux + - Vladimir Jimenez + - Daniel Wendler + - Kacper Gunia + - Arne + - Julien Humbert + - Rob Gagnon + - Nebojša Kamber + - pfleu + - Pouyan Azari + - Claudio Zizza + - Casey Heagerty + - kraksoft + - Claudio Galdiolo + - runephilosof-abtion + - zeggel + - Erik Trapman + - nicofrand + - markspare + - decima + - PHAS Developer + - Jonathan Cox + - Andrii Volin (angy_v) + - Florian Cellier (kark) + - Vincent Jousse + - jerzy-dudzic + - Szymon Dudziak + - Mario Alberto + - Ali Zahedi (aliz9271) + - Michel ANTOINE (antoin_m) + - Roman Martinuk + - bram vogelaar (attachmentgenie) + - Baptiste Pottier (baptistepottier) + - Benoît WERY (benoitwery) + - Boolean Type (boolean_type) + - Boris Sondagh (botris) + - Mickaël Bourgier (chapa) + - Cliff Odijk (cmodijk) + - Colin DeCarlo (colindecarlo) + - Andrew Martynjuk (crayd) + - Doug Smith (dcsmith) + - Jan Schütze (dracoblue) + - Damian Zabawa (dz) + - Dmitriy Fishman (fishmandev) + - Georgiana Gligor (gbtekkie) + - oussama khachiai (geekdos) + - Gonzalo Alonso (gonzakpo) + - Daniel Kucharski (inspiran) + - Maxime Doutreluingne (maxdoutreluingne) + - Ashen one (berbadger) + - Jay Williams (jaywilliams) + - Jelmer Snoeck (jelmersnoeck) + - Jeroen v.d. Gulik (jeroen) + - Janne Vuori (jimzalabim) + - Kane Menicou (kane_menicou) + - Dmitry Kolesnikov (kastaneda) + - Tommy Quissens (quisse) + - Arnaud B (krevindiou) + - Loïc Sapone (loic_sapone) + - Kostas Loupasakis (loupax) + - Markus Thielen (mathielen) + - Mehmet Gökalp (mehgokalp) + - gertdepagter + - Cyril Krylatov + - Michal Landsman + - Oleksandr Savchenko (asavchenko) + - Michael Smith (michaelesmith) + - Ryszard Piotrowski (richardpi) + - Ludwig Ruderstaller (rufinus) + - Nuno Ferreira (nunojsferreira) + - Nuno Pereira (nunopereira) + - Oliver Davies (opdavies) + - ousmane NDIAYE (ousmane) + - Pierre-Yves Dick (pyrrah) + - Paulo Rodrigues Pinto (regularjack) + - Richard Perez (richardpq) + - Slaven (sbacelic) + - Urs Kobald (scopeli) + - Maximilian Ruta + - James Seconde (secondejk) + - Matthew Setter (settermjd) + - Stéphane HULARD (shulard) + - Simon Rolland (sim07) + - Simon Berton (simonberton11) + - Giovanni Gioffreda (tapeworm) + - Thierry Geindre (tgeindre) + - Daniel Ancuta (whisller) + - ameotoko + - Andrey Lukin (wtorsi) + - Yannick ROGER (yannickroger) + - Danilo Sanchi (danilo.sanchi) + - Markus Virtanen + - Sebastian Klaus + - Zamir Memmedov (zamir10) + - Eric Tucker + - Frank J. Gómez + - Alex Savkov + - Andy Truong + - Etilawin + - Pedro Cordeiro + - Michael Staatz + - Rick Burgess + - Christian Oellers + - Guilherme Donato + - NicolasPion + - Tomasz Ducin (tkoomzaaskz) + - Epskampie + - Joppe de Cuyper + - Jose R. Prieto + - Raphaël Riehl + - jakumi + - Vico Dambeck + - Christophe Boucaut + - yositani2002 + - Danny + - runawaycoin + - lusavuvu + - Raphael Michel + - Samuel Wicky + - Petr Kessler + - Florian Belhomme + - KosticDusan4D + - linuxprocess + - Jon Eastman + - François MARTIN + - Chris8934 + - Postal (postal) + - Peter WONG + - Robert Koller (robob4him) + - Mickaël Blondeau (mickael-blondeau) + - Hossein Vakili + - partulaj + - Rami Dridi + - Ahmed Bouras + - Martijn Zijlstra + - Vadim Bondarenko + - Justas Bieliauskas + - Aurélien MARTIN + - Kilian Schrenk + - Andreas Larssen + - Alex-D (alexd) + - saf (asd435) + - Benoît Durand (bdurand) + - Chase Noel (chasen) + - Roman (grn-it) + - Filip Grzonkowski (grzonu) + - Jason McCallister (jasonmccallister) + - Eugene Dounar + - Qiangjun Ran (jungle) + - michael kimsal (kimsal) + - Liang Jin Chao (leunggamciu) + - Vincent Terraillon (lou-terrailloune) + - Vladimir Schmidt (morgen) + - Linas Linartas (linas_linartas) + - Timur Murtukov (murtukov) + - Nikola Kuzmanović (nkuzman) + - Eirik Alfstad Johansen (nmeirik) + - Chabbert Philippe (philippechab) + - Konstantin (phrlog) + - Rodrigo Rigotti Mammano (rodrigorigotti) + - Yosip Curiel (snake77se) + - Stefan Grootscholten (stefan_grootscholten) + - Matthieu Braure (taliesin) + - Prakash Thapa (thapame) + - Arnaud VEBER (veberarnaud) + - Sarah-eit + - sebgarwood-gl + - Lacy (200ok) + - Serge Velikanov + - Richard Miller + - Christian Kolb (liplex) + - Thomas BILLARD + - Pascal MONTOYA (pmontoya) + - Julien EMMANUEL + - Dominik Pietrzak + - Jordan Bradford + - renepupil + - wadjeroudi + - Eliú Timaná + - Andrey Melnikov + - Vincent + - fb-erik + - Quentin Thiaucourt (quentint) + - Ala Eddine khefifi + - Cosmic Mac + - Thibaut Leneveu + - Oliver Adria + - Walkoss + - Andrey Tkachenko + - AntoineRoue + - Jules Lamur + - Virginia Meijer + - Jannik + - Pierre Spring + - Crushnaut + - Shaun Simmons (simshaun) + - andrecadete + - David Schmidt + - Cesare + - fernandokarpinski + - Jordi Freixa Serrabassa + - Kiel Goodman + - Constantin Ross + - sebpacz + - Josef Vitu + - Paul Coudeville + - Jarosław Jakubowski (egger1991) + - Paweł Małolepszy (pmalolepszy) + - Guillaume MOREL + - Émile PRÉVOT + - xavierkaitha94 + - obsirdian + - Mickael GOETZ + - Valentin GRAGLIA + - figaw + - ThamiSadouk + - Charly + - phiamo + - Gytis Šk + - Илья + - Arnaud Lemercier + - Anani Ananiev + - Egidijus Girčys (egircys) + - DerStoffel + - Marek Szymeczko + - clément larrieu + - Ante Crnogorac + - Mike Bissett + - Epari Siva Kumar + - Matthias + - Giovanni Toraldo + - Andreas + - Halil Özgür + - Christopher + - illusionOfParadise + - niebaron + - Works Chan + - jordanjix + - dearaujoj + - Valerio Colella + - Robert Treacy (robwasripped) + - David Harding + - mocrates + - Andrei Petre + - Art Matsak + - asartalo + - Kevin Wojniak + - Volodymyr Stelmakh + - Morf + - Jan Myszkier + - manseuk + - Philipp Bräutigam + - tikoutare + - Kanat Gailimov + - Micha Alt + - Grégory SURACI + - Paweł Farys + - Punt + - Rafa Couto + - Gabriel Theron + - Ian Mustafa + - Thierry Goettelmann + - Sven Luijten + - Brendan Lawton + - Nikita + - Luca Lorenzini + - wbob + - Evgeniy Gavrilov + - Al Bunch + - Clorr + - Daniele Ambrosino + - tobiasoort + - Tymoteusz Motylewski + - fdarre + - Zenobius + - Mbechezi Mlanawo + - David McKay + - ipf + - Andrii Sukhoi + - Cory Becker + - Florian Moser + - Kolja Zuelsdorf + - MWJeff + - Andrius Ulinskas (andriusulins) + - Nico + - kruglikov + - Kevin Raynel + - DanielEScherzer + - Jay-Way + - Felipe Martins + - Lee Boynton + - Jeremy Emery + - beejaz + - tmihalik + - Steve Winter + - pcky + - Parthasarathi GK + - m_hikage + - norfil + - adreeun + - Giulio De Donato + - Sylvain Lelièvre + - Michaël Perrin + - Chris Halbert + - temenb + - Luc + - damienleduc + - Carwyn Moore + - Nico Schoenmaker + - Kevin + - GiveMeAllYourCats + - Matthew Thomas + - wkania + - EtienneHosman + - Matt Kirwan + - Daniel Kozák + - z38 + - Bartek Nowotarski + - mimol91 + - Daniel Santana + - Marius Balčytis + - Rick West + - Richard Hoar + - Reza + - Slobodan Stanic + - Alex Salguero + - manoakys + - Roberto Lombi + - Łukasz Korczewski + - rklaver + - Joe Thielen + - marcusesa + - Pierre Trollé + - Daniele Orler + - Cyril Mouttet (placid2000) + - Robert Parker (yamiko_ninja) + - Patrik Pacin + - Piotr Strugacz + - René Backhaus + - Kieran Black + - guesmiii + - Danny Witting + - morrsky + - Thibaut Selingue + - Dukagjin Surdulli + - Max R + - Etshy + - E Demirtas + - antoinediligent + - Geert Clerx + - Maciej Kosiarski + - royswale + - fberthereau + - Mark Fischer, Jr + - muxator + - Franz Holzinger + - Julian Wagner + - Deepak Kumar + - Nikolai Plath + - jeanhadrien + - Felix Schnabel + - Kevin Wojniak + - Pierre Bobiet + - Tobias Hermann + - Greg Pluta + - Dmitriy + - Michał Wujas + - Marco Barberis + - homersimpsons + - Tobias Sette + - Katharina Störmer + - Javier Espinoza + - Pierre + - Karin van den Berg + - Dhanushka Samarakoon + - Philipp Christen + - Serhii Polishchuk + - Alex Kyriakidis + - Ali Arfeen + - sebio + - Lamari Alaa + - jpache + - Nelson da Costa + - Med Ghaith Sellami + - Jake Bell + - Lars + - VisionPages + - Seikilos + - CodyFortenberry + - nietonfir + - Hugo Locurcio + - Romain GRELET + - Andréas Hanss + - sr972 + - Adam Duffield + - Harry van der Valk + - pavemaksim + - aykin + - joelindix + - denniskoenigComparon + - Vitaliy Zurian + - Иван + - Ozan Akman + - Benjamin Porquet + - Alex Oroshchuk + - Pjotr Savitski + - Jean-David Daviet + - Olivier Lechevalier + - Leny BERNARD + - Michael H + - Hocdoc + - Gabriel Bugeaud + - Mikhail Kamarouski + - Sergey Belyshkin + - Cellophile + - Gaetan Rouseyrol + - scriptibus + - Jace25 + - Sylvain Ferlac + - Kamil Breguła + - kevin + - Gennadi Janzen + - András Debreczeni + - Mustafa Ehsan Alokozay + - Marco + - Artem Henvald + - Nikita Nyatin + - David Baucum + - Jeroen Seegers + - Rémi Andrieux (pimolo) + - Veltar + - Matheus Pedroso + - marcagrio + - Gilles Fabio + - Kélian Bousquet + - TheSidSpears + - Ezequiel Esnaola + - GNi33 + - Andrew Cherabaev + - Alexandre Bertrand + - peaceant + - Mohsen + - adreeun + - MaharishiCanada + - GoT + - Jesús Miguel Benito Calzada (beni0888) + - jdevinemt + - Piotr Potrawiak + - Yann Klis + - Christoph Schmidt + - zeroUno + - Mickaël + - jenyak + - Jan Richter + - Pinchon Karim + - Arndt H. Ziegler + - Xavier + - matteopoile + - dpfaffenbauer + - Oleg Zinchenko + - Menachem Korf + - proArtex + - fplante + - Ruslan + - Nelu Buga + - Rylix + - Arthur Hazebroucq + - JHGitty + - Pedro Gimenez + - Johan de Jager + - Thierry Thuon + - Stephan Dee + - Shamsi Babakhanov + - Charles Winebrinner + - timo002 + - Xavier RIGAL + - Enache Codrut + - Vladimir Jimenez + - mismailzai + - radnan + - Iker Ibarguren + - Bartek Chmura + - Alessio Barnini + - Nicolas Mugnier + - Nitaco + - Alex Normand + - Fouad + - Lucas Pussacq + - Alexandre HUON + - apiotrowski + - vladyslavstartsev + - Christian Alexander Wolf + - Vladimir Gavrylov + - rschillinger + - The Phrenologist (phreno) + - tabbi89 + - John Spaetzel + - Harald Leithner + - Reinier Butôt + - Levi Durfee + - Willem Stuursma-Ruwen + - Théo FIDRY + - Benj + - Maximilian Bosch + - richardmiller + - David + - Sakulbl + - Elbert van de Put + - antonioortegajr + - Florian Rusch + - zulkris + - Dzamir + - Boris Shevchenko + - Kevin Warrington + - Peyman Mohamadpour + - Quentin ADADAIN + - Andrei + - Robin Gloster + - Bram de Smidt + - Zahir Saad Bouzid + - Jonathan Holvey + - pavdovlatov + - Linus Karlsson + - Jason Johnstone + - Pim van Gurp + - Szurovecz János + - Υоаnn B + - Adiel Cristo + - BrnvrlUoeey + - beachespecially + - mbehboodian + - Sascha Egerer + - Martin Černý + - Yves ASTIER + - Dmitri Perunov + - Daniel Karp + - Laurent Marquet + - Jure Žitnik + - Bruno Casali + - Kevin de Heer + - fullbl + - Christian Heinrich + - Jose Diaz + - kohkimakimoto + - Faizan Shaikh + - Frederik Schubert + - Stacy Horton + - Sébastien Lourseau + - Nathan Giesbrecht + - Sebastian Bergmann + - Paweł Tekliński + - Michaël Demeyer + - AdrianBorodziuk + - Edwin + - ruslan-fidesio + - mvanmeerbeck + - phoefnagel + - ioanok + - Chris Bitler + - Mihail Kyosev (php_lamer) + - Alexey Rogachev + - Thomas LEZY + - Matěj Humpál + - Gintautas + - guangle + - Kwadz + - Gergely Pap + - sparrowek + - Travis Carden + - Guillaume Lasset + - Léo + - berbeflo + - Dmytro Bazavluk + - ismail BASKIN + - Simon Epskamp + - Theo Tzaferis + - Mantas Varatiejus + - Josh Kalderimis + - kallard1 + - Alexander Dubovskoy + - hamzabas + - Leo + - sirprize + - VosKoen + - ubick + - Aurélien Morvan + - timglabisch + - Deng Zhi Cheng + - alexsaalberg049 + - Dincho Todorov + - Mohammad + - Richard Tuin (rtuin) + - Gabriel Albuquerque + - John Doe + - Sven Liefgen + - Greg Berger + - Alex Soyer + - Clément + - Massimo Ruggirello + - Artem Ostretsov + - ondra + - Antonio Jesús + - Nextpage + - Robert Podwika + - Julien Janvier + - Dan Zera + - Elliot + - Francesco Abeni + - Denis Dudarev + - Rémy Issard + - hanneskaeufler + - progga + - Jevgenijus Andrijankinas + - concilioinvest + - Paweł Czyżewski + - Richard Lynskey + - Clement Ridoret + - Bob D'Ercole + - Erwann MEST (_kud) + - Abdellatif Derbel (abdellatif) + - Remi + - Mark Brennand (activeingredient) + - Adrián Ríos (adridev) + - Aaron Edmonds (aedmonds) + - Jérôme (ajie62) + - Alejandro García Rodríguez (alejgarciarodriguez) + - Alfonso Machado Benito (almacbe) + - Jérémy LEHERPEUR (amenophis) + - Amine Matmati (aminemat) + - Anand (anandagra) + - Andrew D Battye (andrew_battye) + - Atchia Mohammad Annas Yacoob (annas-atchia) + - Alexey Bakulin (bakulinav) + - Andries van den Berg (ansien12) + - Anthony Sterling (anthonysterling) + - Łukasz Bownik (arkasian) + - Arnaud Salvucci (arnucci) + - Andrey Shark (astery) + - Alexander Vorobiev (avorobiev) + - Aldo Zarza (azarzag) + - Babar Al-Amin (babar) + - Norman Soetbeer (battlerattle) + - Fabien Lasserre (fbnlsr) + - Behram ÇELEN (behram) + - Belgacem TLILI (belgacem) + - belghiti idriss (belghiti) + - Mathieu + - Sebastian G. (bestog) + - Clément Notin + - Dennis Bijsterveld (bijsterdee) + - Adam Boardman (boardyuk) + - Bartłomiej Zając (bzajac) + - Alistair (phiali) + - Catalin Criste (catalin) + - Alexander Kim + - Jean Pasqualini + - Catalin Minovici (catalin_minovici) + - Carlos Zuniga (charlieman) + - Christiaan Baartse (christiaan) + - V. K. (cn007b) + - Cosmin Mihai Sandu (cosminsandu) + - Kristof Coomans (cyberwolf) + - CHARBONNIER (cyrus) + - Dalius Kalvaitis (daliuskal) + - Davi Tavares Alexandre (davialexandre) + - David Negreira Rios (davidn) + - Derek Roth (derekroth) + - Abdelilah Boudi (devsf3) + - Timotheus Israel (dieisraels) + - Davor Plehati (dplehati) + - Alex Ghiban (drew7721) + - Dan Tormey (dstormey) + - Dmitry Vapelnik (dvapelnik) + - Marc Michot (eclae) + - Fatih Ergüven (erguven) + - Erwan Richard (erichard) + - Benjamin Toussaint + - Erik (erikroelofs) + - Sergey Falinsky (falinsky) + - Florian Semm (floriansemm) + - Fayez Naccache (fnash) + - Frank Stelzer (frastel) + - Gabriel Théron (g.theron) + - Simon Perdrisat (gagarine) + - Jérémy Jarrié (gagnar) + - Patrick Mota (ganon4) + - David Rolston (gizmola) + - Vadym (rvadym) + - Benjamin Hubert (gouaille) + - Greg Box (gregfriedrice) + - Victor Melnik (gremlin) + - Grzegorz Balcewicz (gbalcewicz) + - Guillaume Sylvestre (gsylvestre) + - Guillaume HARARI (guillaumeharari) + - Augustin Chateau (gus3000) + - Houssem ZITOUN + - Vladyslav Riabchenko + - Cristiano Cattaneo (ccattaneo) + - Daniel Platt (hackzilla) + - ABOULHAJ Abdelhakim (hakim_aboulhaj) + - Hans Stevens (hansstevens) + - Thomas Rudolph (holloway) + - Nik G (iiirxs) + - Tim Werdin + - Hugo Nicolas (jacquesdurand) + - Janko Diminic (jankod) + - Jonathan Lee (jclee2) + - Nico Th. Stolz (jeireff) + - Jose F. Calcerrada (jfcalcerrada) + - Jibé (jibe0123) + - jean-marie leroux (jmleroux) + - Joan Teixido (joanteixi) + - Joshua Morse (joshuamorse) + - James Cryer (jrcryer) + - Julien Chaumond (julien_c) + - Julius (julius1) + - rs + - Kenan Kahrić (kahric) + - Karsten Gohm (kasn) + - Kik Minev (kikminev) + - Kobe Vervoort (kobevervoort) + - Philip Ardery + - Konrad pap (konrados) + - Vincent AMSTOUTZ (vincent_amstz) + - Korstiaan de Ridder (korstiaan) + - Leonardo Losoviz (leoloso) + - Ricardo Peters (listerical) + - lobodol (lobodol) + - Louis Racicot (lord_stan) + - LOUVEL Mathieu (louvelmathieu) + - Maikel Ortega Hernández (maikeloh) + - imam harir (luxferoo) + - Joachim Martin (michaoj) + - Kevin Papst + - Pierre Maraitre + - Kévin LE LOUËR + - Marko Kunic (kunicmarko20) + - Eduardo Thomas Perez del Postigo (aruku) + - Paulius Masiliūnas (pauliuz) + - Fabian Becker + - seangallavan + - Maninder Singh (maninder) + - Rémy Vuong (rvuong) + - Manuel Agustín Ordóñez (manuel_agustin) + - Martijn Gastkemper (martijngastkemper) + - samson daniel (samayo) + - Martin Ninov (martixy) + - Manuel Transfeld + - Aleksander Cyrkulewski (martyshka) + - Sam Van der Borght (samvdb) + - Matthieu Danet (matthieu-tmk) + - Carlos Jimenez (saphyel) + - Maurice Svay (mauricesvay) + - Lorenzo Milesi (maxxer) + - Sylvester Saracevas (saracevas) + - Maximilien BERNARD (mb3rnard) + - Marius Büscher (mbuescher) + - Sebastián Poliak (sebastianlpdb) + - Mindaugas Liubinas (meandog) + - AntoJ (merguezzz) + - Csaba Maulis (senki) + - Simone Gentili (sensorario) + - Sergey Podgornyy (sergey_podgornyy) + - Marcel Serra Julià (serrajm) + - Sethunath K (sethunath) + - Woody Gilk (shadowhand) + - Wil Moore (wilmoore) + - Shambhu Kumar (shambhu384) + - Yuri Tkachenko (tamtamchik) + - Simon Van Accoleyen (simonvanacco) + - Slava Belokurski (slavchoo) + - Pol Romans (snamor) + - Steven Chen (squazic) + - Stefan Blanke (stedekay) + - Nicolae Astefanoaie (stelu26) + - Paris mikael (stood) + - Stanislav Zakharov (strannik) + - Sven (svdv22) + - Patrik Gmitter (patie) + - Sven Zissner (svenzissner) + - Artur 'Wodor' Wielogorski + - Jeroen + - Panda INC (pandalowry) + - Kevin Pires (takiin) + - Björn Fromme (bjo3rn) + - Gabriel Pillet (tentacode) + - Toni Conca (tonic) + - Tom Schuermans (tschuermans) + - Attila Egyed (tsm) + - Unai Roldán (unairoldan) + - Varun Agrawal (varunagw) + - Josh Freeman (viion) + - Marvin Butkereit + - Vivien Tedesco (vivient) + - skipton-io + - Daniel (voodooprograms) + - WILLEMS Laurent (willemsl) + - Willem-Jan Zijderveld (wjzijderveld) + - Wojciech Międzybrodzki (wojciechem) + - Alexandre Mallet (woprrr) + - Paulius Podolskis (wsuff) + - xthiago (xthiago) + - Karel (xwb) + - Daniel LIma (yourwebmaker) + - Yuriy Sergeev (youser) + - Ziad Jammal (ziadjammal) + - Zsolt Javorszky (zsjavorszky) + - Ivan Zugec (zugec) + - Lukas W + - babache + - zan-vseved + - manu-sparheld + - ArlingtonHouse + - Gus + - Reza Rabbani + - yordandv + - mehlichmeyer + - Jens Pliester + - Benjamin Sureau + - Krap + - David Vigo + - KalleV + - Christopher Tatro + - Pooyan Khanjankhani + - Ellis Benjamin + - Sam Jarrett + - Sela + - Nelson da Costa + - Andrea Bergamasco (vjandrea) + - Axel Vankrunkelsven + - snroki + - jivot + - miqrogroove + - Oussama GHAIEB (oussama_tn) + - Thao Nguyen (thaowitkam) + - Christophe Meneses + - Sudhakar Krishnan + - Michaël Perrin + - Kevin + - Kevin + - Christian Schaefer (caefer) + - Hugo Casabella (casahugo) + - Charles Pourcel (ch.pourcel) + - Stephan Savoundararadj (lkolndeep) + - Jon Cave + - Travis Yang (oopsfrogs) + - Francisco Javier Aceituno (javiacei) + - Jo Meuwis (jo_meuwis) + - Joel Costa (joelrfcosta) + - Maxim Spivakovksy (lazyants) + - Lucian Tugui (luciantugui) + - Mehdi Tazi (mehditazi9) + - Michał (mleczakm) + - Gyula Szabó (szabogyula) + - Tomas Nemeikšis (niumis) + - tamir van-spier (tamirvs) + - Joe Mizzi (themizzi) + - Thomas Lomas (tomlomas) + - Kristijan Stipić (stipic) + - Poulette Christophe (totof6942) + - Omar Brahimi (omarbrahimi) + - Sebastian Blum (sebiblum) + - makmaoui + - Olivier Revollat (o_revollat) + - juliendidier + - Michael Cullum (unknownbliss) + - Vincent Amstoutz + - Aurélien ADAM (aadam) + - Arnaud Thibaudet (kojiro) + - Alessandro Podo + - Fabien Schurter + - Michał Szczech (miisieq) + - Carlos Reig (statu) + - Nico Hiort af Ornäs + - Ian Kevin Irlen (kevinirlen) + - ifiroth + - Jordan Aubert (jordanaubert) + - Nicolas GIRAUD (niconoe) + - Romain Card + - Ilya Bakhlin Lebedev + - Alessandro Podo + - Hamza Makraz + - Pierre MORADEI + - Julien "Nayte" Robic + - Niklas + - Turdaliev Nursultan (nurolopher) + - Shamil Nunhuck (shamil) + - Bart Vanderstukken (sneakyvv) + - Spomky + - Thomas Choquet (tchoquet) + - Marcus Stöhr + - Denis Rendler + - Simon Daigre (simondgre) + - Markus Weiland (advancingu) + - Matheo D + - romain + - Jacob Tobiasz (jakubtobiasz) + - Maxime Douailin + - Jean-François Lépine (halleck45) + - Sait KURT (deswa) + - Maarten de Keizer (maartendekeizer) + - Marwâne (beamop) + - Jannes Drijkoningen (jannesd) + - Kilian Riou (redheness) + - Alexandre Gérault (alexandre-gerault) + - Thomas Choquet (chqthomas3) + - Григорий + - Barun + - Zéfyx + - Pierre Sv (rrr63) + - Denis Soriano (dsoriano) + - Laurent Marquet + - Daniel Garzon (arko) + - Kevin T'Syen (noscope) + - Nehal Gajjar + - jmangarret + - norbert-n + - Vladimir + - Thomas (razbounak) + - Aymen Bouchekoua (nightfox) + - Jan + - Augustin Delaporte + - asandjivy + - YummYume + - Leanna Pelham + - Daniel F. (ragtek) + - Adrien LUCAS + - twisted1919 + - fbuchlak + - Kevin + - Mrtn Schndlr + - Ricardo Rentería + - Sven Petersen + - Yoan Bernabeu + - Simon Riedmeier (simonsolutions) + - Steven DUBOIS (stevenn) + - Colin Poushay (poush) + - Hugo Seigle + - Hendrik Pilz (hendrikpilz) + - Rick Kuipers + - Vancoillie + - optior + - Christoph Grabenstein + - Benoit Jouhaud (bjouhaud) + - David + - matheo + - Jan Christoph Beyer + - Josenilton Junior (zavarock) + - kempha + - Simon + - Marie CHARLES (mariecharles) + - Matijn Woudt + - Valentin GARET (vgaret) + - Nicolas Rigaud + - Jonathan Huteau (jonht) + - Pierre Joye (pierre) + - lucbu + - Bastien70 + - Zbigniew Czapran (zczapran) + - Sander Verkuil (sander-verkuil) + - Fabien (fabiencambournac) + - VelvetMirror + - Bryan J. Agee + - Niels Vermaut (nielsvermaut) + - Fabien Papet + - yoye + - Игорь Дмитриевич Чунихин (6insanes) + - Stephan + - Krzysztof Ilnicki (poh) + - Cassian Assael (crozet) + - Matthew Ratzke (flyboarder) + - Sven Scholz + - Guillaume PARIS (gparis) + - Xavier Laviron (norival) + - Michael Grinko + - Phil Wright- Christie (philwc) + - Edson Medina + - Denys Pasishnyi (dpcat237) + - Plamen + - (H)eDoCode + - Maximilian + - Iv Po + - Greg Berger + - Frédéric Lesueurs + - Matthieu Renard + - Jonas De Keukelaere + - Luc Hidalgo (luchidalgo) + - Julien Dubois + - Ondrej Vana (kachnitel) + - Marchegay (xaviermarcheay) + - Maxime Steinhausser + - Bart Heyrman + - Morgan Thibert (o0morgan0ol) + - Baptiste Fotia (zak39) + - LesRouxDominerontLeMonde + - Yoann B (yoann) + - Johan de Jager (dejagersh) + - Jacob Dreesen + - Marco Polichetti + - Joe + - Jérémy CROMBEZ + - Raphaël Davaillaud + - vesselind + - Joseph Bielawski + - Yannick + - Nieck Moorman + - John Ballinger + - Bob van de Vijver + - github-actions[bot] + - Nicolas Lœuillet (nicosomb) + - Antoine Durieux (adurieux) + - Roger Webb (webb.roger) + - sander Haanstra (milosa) + - Denis (ruff3d) + - Pierre-Emmanuel CAPEL (pecapel) + - Lucas Courot (lucascourot) + - Pavel Nemchenko (nemoipaha) + - Jerome Guilbot (papy_danone) + - Adam + - Ahmed Siouani (ahsio) + - matthieu88160 + - Grant Gaudet + - bdujon + - Simon BLUM (simonblum) + - Tom Schwiha (tomschwiha) + - Thomas Miceli (tomus) + - stehled + - healdropper + - Sebastian Kuhlmann (zebba) + - Saidou GUEYE + - Yoan Arnaudov (nacholibre) + - Florian + - Michael Petri (michaelpetri) + - Levin + - Mark Deanil Vicente (dvincent3) + - Laurent Moreau (laulibrius) + - Robin Weller + - Benjamin Zaslavsky + - Mart Kop + - Ruud Kamphuis + - Dmytro + - Yakov Lipkovich + - Fabien Bourigault + - Leonard Simonse + - Rhodri Pugh + - Tristan Darricau + - John Williams + - Nadim AL ABDOU + - Mateusz Anders + - Wanne Van Camp + - Jasperator + - anton + - Marius Adam + - Vladimir Jimenez + - Robin + - Gary Kovar + - Jalen + - Tomi Saarinen (tomis) + - Issam KHADIRI (ikhadiri) + - Wagner Nicolas (n1c01a5) + - Lorenzo Ruozzi (lruozzi9) + - Marko Kaznovac + - DOEO + - Marc Wustrack (muffe) + - Loïc Caillieux (loic.caillieux) + - Alexey Pyltsyn (lex111) + - benti + - Dennis de Best (monsteroreo) + - Ludwig Bayerl (lbayerl) + - Carlos Sánchez (carlossg00) + - Darien Hager + - Jérémy Jumeau (jeremyjumeau) + - Paweł Krynicki (kryniol) + - Tamás Molnár (moltam) + - Robin Willig (dragonito) + - Robert Parker (yamiko) + - Pedro Nofuentes (pedronofuentes) + - mojzis + - Fanny Gautier + - Alexey Samara + - gong023 + - Jan Dorsman + - xaav + - Aurelijus Banelis (aurelijusb) + - Christophe Debruel (krike06) + - shkkmo + - Yaroslav Kiliba + - Tony Cosentino + - burki94 + - Kostya + - alexchuin + - Szyszewski + - Nils Silbernagel + - Adrien + - Andrei Chugunov + - Jan G. (jan) + - Ahmed Raafat (luffy14) + - azielinski + - Thibault Gattolliat (crovitche) + - Dimitar + - Florent Destremau + - Marc Neuhaus (mneuhaus) + - Niklas Grießer + - Cullen Walsh + - damien-louis + - Olena Kirichok + - Julian Mallett (jxmallett) + - Romain Norberg + - Steven + - hector prats (jovendigital) + - Koen van Wijnen (infotracer) + - Michael Y Kopinsky (mkopinsky) + - Roger Llopart Pla (lumbendil) + - David Zuelke (dzuelke) + - Abdelkader Bouadjadja (medinae) + - Eduardo Gulias Davis + - Dmitry Vishin (wishmaster) + - Alfonso M. García Astorga (alfonsomga) + - José María Sanchidrián (sanmar) + - Diego Gullo (bizmate) + - martin05 + - Bruno Vitorino + - Noel + - beram (beram) + - Markus Mauksch + - Mitchell + - Avindra Goolcharan + - Florent + - roga + - Timon F. (timon) + - Denis-Florin Rendler + - Titouan B + - IlhamiD + - Alexander Marinov + - Manoj Kumar + - Nazar Mammedov + - Maxime Nicole + - pecapel + - Cadot.eu & Co. + - Matthias Gutjahr (mattsches) + - Dan Abrey + - Matthieu Lempereur (matthieulempereur) + - Sylvain Blondeau + - Maelan LE BORGNE (maelanleborgne) + - jmsche + - Rutger + - Tim Glabisch + - g@8vue.com + - danjamin + - Ondřej Vodáček + - mark2016 + - Petr (rottenwood) + - Łukasz Pior (piorek) + - revollat + - Jorick Pepin (jorick) + - micter59 + - unknown + - Rob + - Tajh Leitso (tajh) + - Wolfgang Weintritt (wolwe) + - Bram van Leur (bvleur) + - BooleanType + - Luke Kysow + - Zac Sturgess (zsturgess) + - t.le-gacque + - Hugo Locurcio + - Mohd Shakir Zakaria (mohdshakir) + - Yohann Durand (yohann-durand) + - Konstantin Tjuterev (kostiklv) + - Alexandru Furculita ♻ + - amelie le coz (amelielcz) + - Thibaud BARDIN (irvyne) + - Jérémy BLONDEAU (jblondeau2) + - Adoni Pavlakis + - valepu + - Hans Allis (hansallis) + - Marek Brieger (polmabri) + - Lluis Toyos (tolbier) + - Jarvis Stubblefield (ballisticpain) + - Mathieu Ducrot (mathieu-ducrot) + - Daniel Santana + - Adam W (axzx) + - Francisco Calderón (fcalderon) + - HONORE HOUNWANOU (mercuryseries) + - yanickj + - Evan Owens + - S Berder + - Félix Fouillet + - Tobias Berchtold + - Pavel Bezdverniy + - Dr. Balazs Zatik + - Carsten Blüm (bluem) + - Omer Karadagli (omer) + - OrangeVinz (orangevinz) + - ThomasGallet + - Jarek Ikaniewicz + - Daniel Degasperi (ddegasperi) + - Milan (milan) + - Patrick Bußmann + - Kamil Kuzminski (qzminski) + - Happy (ha99ys) + - AlexKa + - Foksler (foksler) + - Sacha Durand (sacha_durand) + - Tom Grandy + - Epskampie + - Francesco Tassi (ftassi) + - Jason Bouffard (jpb0104) + - Katharina Floh (katharina-floh) + - Christopher + - Nicolas Hart (nclshart) + - Christopher Moll + - Gianluca Farinelli (rshelter) + - Jorge Luis Betancourt (jorgelbg) + - Yannick (yannickdurden) + - Dynèsh Hassanaly (dynesh) + - Tom Maaswinkel (thedevilonline) + - Thibault Miscoria (tmiscoria) + - Alexpts (alexpts) + - Michiel Missotten (zenklys) + - Benjamin Clay (ternel) + - Mark Challoner + - Jacob Mather (jmather) + - Fabien Bourigault + - Adil YASSINE ✌️ (sf2developer) + - Savvas Alexandrou (savvasal) + - Tim Jabs + - LucileDT + - Open Orchestra (open-orchestra) + - Salavat Sitdikov (sitsalavat) + - Iulian Popa (iulyanp) + - AmalricBzh + - htmlshaman1 + - Aleksandr Frolov (thephilosoft) + - Valantis Koutsoumpos + - Slava Fomin II (s-fomin) + - Raúl Continente (raulconti) + - Daniel West (silverbackdan) + - Martin Bens + - Robert + - Ross Cousens + - Murilo Lobato (murilolobato) + - Tim Krase + - Kendrick + - Bastien Picharles (kleinast) + - Metfan (metfan) + - Sylvain Combes (sylvaincombes) + - Daniel Haaker (dhaaker) + - Mark (markchicobaby) + - Lenkov Michail (alchimik) + - Florent DESPIERRES (fdespierres) + - Anton + - Cyril Lussiana + - Valentin Silvestre (vasilvestre) + - Vincent Le Biannic + - Adam Szaraniec (mimol) + - Abdellah Ramadan (abdellahrk) + - Tim Hovius (timhovius) + - Julian (c33s) + - Ryan Castle (ryancastle) + - Chad Meyers (nobodyfamous) + - Ben Huebscher (huebs) + - William JEHANNE (william_jehanne) + - mhor (mhor) + - richardudovich + - pathmissing + - Soltész Balázs + - Ben Glassman (benglass) + - Thomas Botton (skeud) + - Mohammed Rhamnia (rmed19) + - Thomas Talbot + - Douglas Naphas + - Ilya Antipenko + - karzz + - Markus Frühauf + - Damien Carrier (mirakusan) + - Nassim + - Enzo Santamaria + - Jonathan Finch + - Herbert Muehlburger + - Dawid Królak (taavit) + - Toni Peric + - Danil Pyatnitsev (pyatnitsev) + - Julien Bonnier (jbonnier) + - Geert Eltink + - Martin Melka + - Bert Van de Casteele + - Olivier Bacs (obax) + - Ayyoub BOUMYA (aybbou) + - Phil Moorhouse (lazymanc) + - Dorthe Luebbert (luebbert42) + - Sylvain + - Michelle Sanver (michellesanver) + - Rafael Mello (merorafael) + - Arthur Hazebroucq + - Michel D'HOOGE (mdhooge) + - Yair Silbermintz (mrglass) + - Patrick McAndrew (patrick) + - Kirill Baranov (u_mulder) + - Mynyx + - Artur Weigandt + - Baptiste Langlade + - Amitay Horwitz (amitayh) + - Manel Sellés (manelselles) + - ahinkle + - Lucas Nothnagel (scriptibus) + - Egidijus Gircys + - fridde + - Evgeniy Guseletov (dark) + - Edoardo Rivello (erivello) + - Malte N (hice3000) + - Elias Van Ootegem + - Boissinot (pierreboissinotlephare) + - Jan De Coster + - Sam Hudson + - Marcus Schwarz diff --git a/README.md b/README.md index d63c544916613..2ca0bfbb35f6f 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,13 @@ Installation Sponsor ------- -Symfony 7.2 is [backed][27] by -- [Sulu][29] -- [Rector][30] +Symfony 7.3 is [backed][27] by +- [Les-Tilleuls.coop][29] -**Sulu** is the CMS for Symfony developers. It provides pre-built content-management -features while giving developers the freedom to build, deploy, and maintain custom -solutions using full-stack Symfony. Sulu is ideal for creating complex websites, -integrating external tools, and building custom-built solutions. - -**Rector** helps successful and growing companies to get the most of the code -they already have. Including upgrading to the latest Symfony LTS. They deliver -automated refactoring, reduce maintenance costs, speed up feature delivery, and -transform legacy code into a strategic asset. They can handle the dirty work, -so you can focus on the features. +**Les-Tilleuls.coop** is a team of 70+ Symfony experts who can help you design, develop and +fix your projects. They provide a wide range of professional services including development, +consulting, coaching, training and audits. They also are highly skilled in JS, Go and DevOps. +They are a worker cooperative! Help Symfony by [sponsoring][28] its development! @@ -96,5 +89,4 @@ and supported by [Symfony contributors][19]. [26]: https://symfony.com/book [27]: https://symfony.com/backers [28]: https://symfony.com/sponsor -[29]: https://sulu.io -[30]: https://getrector.com +[29]: https://les-tilleuls.coop diff --git a/src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php b/src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php index 1efa7d78d0524..3e0b946d688e8 100644 --- a/src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php +++ b/src/Symfony/Bridge/Doctrine/ArgumentResolver/EntityValueResolver.php @@ -73,7 +73,7 @@ public function resolve(Request $request, ArgumentMetadata $argument): array return []; } - throw new NearMissValueResolverException(sprintf('Cannot find mapping for "%s": declare one using either the #[MapEntity] attribute or mapped route parameters.', $options->class)); + throw new NearMissValueResolverException(\sprintf('Cannot find mapping for "%s": declare one using either the #[MapEntity] attribute or mapped route parameters.', $options->class)); } try { $object = $manager->getRepository($options->class)->findOneBy($criteria); diff --git a/src/Symfony/Bridge/Doctrine/Middleware/IdleConnection/Listener.php b/src/Symfony/Bridge/Doctrine/Middleware/IdleConnection/Listener.php index 11f7053c5f702..ad570821d7c76 100644 --- a/src/Symfony/Bridge/Doctrine/Middleware/IdleConnection/Listener.php +++ b/src/Symfony/Bridge/Doctrine/Middleware/IdleConnection/Listener.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; final class Listener implements EventSubscriberInterface @@ -29,6 +30,9 @@ public function __construct( public function onKernelRequest(RequestEvent $event): void { + if (HttpKernelInterface::MAIN_REQUEST !== $event->getRequestType()) { + return; + } $timestamp = time(); foreach ($this->connectionExpiries as $name => $expiry) { diff --git a/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/ListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/ListenerTest.php index 099ab48777133..72fa7e068f67c 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/ListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Middleware/IdleConnection/ListenerTest.php @@ -9,13 +9,14 @@ * file that was distributed with this source code. */ -namespace Middleware\IdleConnection; +namespace Symfony\Bridge\Doctrine\Tests\Middleware\IdleConnection; use Doctrine\DBAL\Connection as ConnectionInterface; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Middleware\IdleConnection\Listener; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; class ListenerTest extends TestCase { @@ -34,10 +35,24 @@ public function testOnKernelRequest() ->willReturn($connectionOneMock); $listener = new Listener($connectionExpiries, $containerMock); + $event = $this->createMock(RequestEvent::class); + $event->method('getRequestType')->willReturn(HttpKernelInterface::MAIN_REQUEST); - $listener->onKernelRequest($this->createMock(RequestEvent::class)); + $listener->onKernelRequest($event); $this->assertArrayNotHasKey('connectionone', (array) $connectionExpiries); $this->assertArrayHasKey('connectiontwo', (array) $connectionExpiries); } + + public function testOnKernelRequestShouldSkipSubrequests() + { + self::expectNotToPerformAssertions(); + $arrayObj = $this->createMock(\ArrayObject::class); + $arrayObj->method('getIterator')->willThrowException(new \Exception('Invalid behavior')); + $listener = new Listener($arrayObj, $this->createMock(ContainerInterface::class)); + + $event = $this->createMock(RequestEvent::class); + $event->method('getRequestType')->willReturn(HttpKernelInterface::SUB_REQUEST); + $listener->onKernelRequest($event); + } } diff --git a/src/Symfony/Bridge/Doctrine/Types/DatePointType.php b/src/Symfony/Bridge/Doctrine/Types/DatePointType.php index 72a04e80cf7ee..565506f2b673e 100644 --- a/src/Symfony/Bridge/Doctrine/Types/DatePointType.php +++ b/src/Symfony/Bridge/Doctrine/Types/DatePointType.php @@ -20,12 +20,12 @@ final class DatePointType extends DateTimeImmutableType public const NAME = 'date_point'; /** - * @param T $value - * - * @return (T is null ? null : DatePoint) - * - * @template T - */ + * @param T $value + * + * @return (T is null ? null : DatePoint) + * + * @template T + */ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?DatePoint { if (null === $value || $value instanceof DatePoint) { diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 4aed1cd3a44c2..eb2e89b94dfb8 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -11,7 +11,6 @@ namespace Symfony\Bridge\Doctrine\Validator\Constraints; -use Doctrine\ORM\Mapping\ClassMetadata as OrmClassMetadata; use Doctrine\ORM\Mapping\MappingException as ORMMappingException; use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\Mapping\ClassMetadata; @@ -294,7 +293,7 @@ private function getFieldValues(mixed $object, ClassMetadata $class, array $fiel throw new ConstraintDefinitionException(\sprintf('The field "%s" is not a property of class "%s".', $fieldName, $objectClass)); } - if ($isValueEntity && $object instanceof ($class->getName()) && property_exists(OrmClassMetadata::class, 'propertyAccessors')) { + if ($isValueEntity && $object instanceof ($class->getName()) && property_exists($class, 'propertyAccessors')) { $fieldValues[$entityFieldName] = $class->propertyAccessors[$fieldName]->getValue($object); } elseif ($isValueEntity && $object instanceof ($class->getName())) { $fieldValues[$entityFieldName] = $class->reflFields[$fieldName]->getValue($object); diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 9d95a8af14ca7..bebf7276a99dc 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -39,7 +39,7 @@ "symfony/security-core": "^6.4|^7.0", "symfony/stopwatch": "^6.4|^7.0", "symfony/translation": "^6.4|^7.0", - "symfony/type-info": "^7.1", + "symfony/type-info": "^7.1.8", "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", "symfony/var-dumper": "^6.4|^7.0", diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index cacc7e4440a81..77bc2b08c8775 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -55,7 +55,7 @@ protected function configure(): void ->addOption('format', null, InputOption::VALUE_REQUIRED, \sprintf('The output format ("%s")', implode('", "', $this->getAvailableFormatOptions()))) ->addOption('show-deprecations', null, InputOption::VALUE_NONE, 'Show deprecations as errors') ->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN') - ->addOption('excludes', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Excluded directories', []) + ->addOption('excludes', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Excluded directories', []) ->setHelp(<<<'EOF' The %command.name% command lints a template and outputs to STDOUT the first encountered syntax error. diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index f1ae7068f11d1..62821fcd81045 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -161,7 +161,7 @@ private function createFieldChoicesList(iterable $choices, string|false|null $tr continue; } - /* @var ChoiceView $choice */ + /** @var ChoiceView $choice */ $translatableLabel = $this->createFieldTranslation($choice->label, $choice->labelTranslationParameters, $translationDomain); yield $translatableLabel => $choice->value; } diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index 9d9bce1e64fcf..4a73c5ba67f66 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -28,7 +28,7 @@ final class FormThemeNode extends Node public function __construct(Node $form, Node $resources, int $lineno, $only = false) { if (null === $only || \is_string($only)) { - trigger_deprecation('symfony/twig-bridge', '3.12', 'Passing a tag to %s() is deprecated.', __METHOD__); + trigger_deprecation('symfony/twig-bridge', '7.2', 'Passing a tag to %s() is deprecated.', __METHOD__); $only = \func_num_args() > 4 ? func_get_arg(4) : true; } elseif (!\is_bool($only)) { throw new \TypeError(\sprintf('Argument 4 passed to "%s()" must be a boolean, "%s" given.', __METHOD__, get_debug_type($only))); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php index 4c6e672a9af2d..cbbc42b9d196e 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubTranslator.php @@ -11,12 +11,19 @@ namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures; +use Symfony\Contracts\Translation\TranslatableInterface; use Symfony\Contracts\Translation\TranslatorInterface; class StubTranslator implements TranslatorInterface { public function trans($id, array $parameters = [], $domain = null, $locale = null): string { + foreach ($parameters as $k => $v) { + if ($v instanceof TranslatableInterface) { + $parameters[$k] = $v->trans($this, $locale); + } + } + return '[trans]'.strtr($id, $parameters).'[/trans]'; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php index e794e88c48473..d71fd6810fd13 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerLintCommand.php @@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass; +use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -49,8 +50,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); + $resolveEnvVars = $input->getOption('resolve-env-vars'); + try { - $container = $this->getContainerBuilder(); + $container = $this->getContainerBuilder($resolveEnvVars); } catch (RuntimeException $e) { $errorIo->error($e->getMessage()); @@ -60,7 +63,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $container->setParameter('container.build_time', time()); try { - $container->compile((bool) $input->getOption('resolve-env-vars')); + $container->compile($resolveEnvVars); } catch (InvalidArgumentException $e) { $errorIo->error($e->getMessage()); @@ -72,7 +75,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - private function getContainerBuilder(): ContainerBuilder + private function getContainerBuilder(bool $resolveEnvVars): ContainerBuilder { if (isset($this->container)) { return $this->container; @@ -99,16 +102,22 @@ private function getContainerBuilder(): ContainerBuilder (new XmlFileLoader($container = new ContainerBuilder($parameterBag = new EnvPlaceholderParameterBag()), new FileLocator()))->load($kernelContainer->getParameter('debug.container.dump')); - $refl = new \ReflectionProperty($parameterBag, 'resolved'); - $refl->setValue($parameterBag, true); + if ($resolveEnvVars) { + $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveParameterPlaceHoldersPass(), new ResolveFactoryClassPass()]); + } else { + $refl = new \ReflectionProperty($parameterBag, 'resolved'); + $refl->setValue($parameterBag, true); + + $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveFactoryClassPass()]); + } $container->getCompilerPassConfig()->setBeforeOptimizationPasses([]); - $container->getCompilerPassConfig()->setOptimizationPasses([new ResolveFactoryClassPass()]); $container->getCompilerPassConfig()->setBeforeRemovingPasses([]); } $container->setParameter('container.build_hash', 'lint_container'); $container->setParameter('container.build_id', 'lint_container'); + $container->setParameter('container.runtime_mode', 'web=0'); $container->addCompilerPass(new CheckAliasValidityPass(), PassConfig::TYPE_BEFORE_REMOVING, -100); $container->addCompilerPass(new CheckTypeDeclarationsPass(true), PassConfig::TYPE_AFTER_REMOVING, -100); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index d042d44b5faa4..d66a5c6fff8b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -48,7 +48,6 @@ use Symfony\Component\Translation\Translator; use Symfony\Component\TypeInfo\Type; use Symfony\Component\Uid\Factory\UuidFactory; -use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Validation; use Symfony\Component\Webhook\Controller\WebhookController; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -1096,7 +1095,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode, callable $e ->validate()->castToArray()->end() ->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(array_merge(class_exists(Email::class) ? Email::VALIDATION_MODES : ['html5-allow-no-tld', 'html5', 'strict'], ['loose']))->defaultValue('html5')->end() + ->enumNode('email_validation_mode')->values(['html5', 'html5-allow-no-tld', 'strict', 'loose'])->defaultValue('html5')->end() ->arrayNode('mapping') ->addDefaultsIfNotSet() ->fixXmlConfig('path') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index d3cefbb28fbe1..0cf63bfea9fca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1159,7 +1159,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $workflow['definition_validators'][] = match ($workflow['type']) { 'state_machine' => Workflow\Validator\StateMachineValidator::class, 'workflow' => Workflow\Validator\WorkflowValidator::class, - default => throw new \LogicException(\sprintf('Invalid workflow type "%s".', $workflow['type'])), + default => throw new \LogicException(\sprintf('Invalid workflow type "%s".', $workflow['type'])), }; // Create Workflow @@ -3320,13 +3320,13 @@ private function registerRateLimiterConfiguration(array $config, ContainerBuilde throw new LogicException(\sprintf('Compound rate limiter "%s" requires at least one sub-limiter.', $name)); } - if (\array_diff($limiterConfig['limiters'], $limiters)) { + if (array_diff($limiterConfig['limiters'], $limiters)) { throw new LogicException(\sprintf('Compound rate limiter "%s" requires at least one sub-limiter to be configured.', $name)); } $container->register($limiterId = 'limiter.'.$name, CompoundRateLimiterFactory::class) ->addTag('rate_limiter', ['name' => $name]) - ->addArgument(new IteratorArgument(\array_map( + ->addArgument(new IteratorArgument(array_map( static fn (string $name) => new Reference('limiter.'.$name), $limiterConfig['limiters'] ))) diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php index f40373a302b45..5d2ecf289b883 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php @@ -182,7 +182,7 @@ public function registerContainerConfiguration(LoaderInterface $loader): void } $file = (new \ReflectionObject($this))->getFileName(); - /* @var ContainerPhpFileLoader $kernelLoader */ + /** @var ContainerPhpFileLoader $kernelLoader */ $kernelLoader = $loader->getResolver()->resolve($file); $kernelLoader->setCurrentDir(\dirname($file)); $instanceof = &\Closure::bind(fn &() => $this->instanceof, $kernelLoader, $kernelLoader)(); @@ -208,7 +208,7 @@ public function registerContainerConfiguration(LoaderInterface $loader): void public function loadRoutes(LoaderInterface $loader): RouteCollection { $file = (new \ReflectionObject($this))->getFileName(); - /* @var RoutingPhpFileLoader $kernelLoader */ + /** @var RoutingPhpFileLoader $kernelLoader */ $kernelLoader = $loader->getResolver()->resolve($file, 'php'); $kernelLoader->setCurrentDir(\dirname($file)); $collection = new RouteCollection(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 7f4b48a18b296..a8567aa3e717e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -338,6 +338,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php index 9b765c36a18e6..f17aad0e3dc60 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/SerializerCacheWarmerTest.php @@ -21,6 +21,23 @@ class SerializerCacheWarmerTest extends TestCase { + private PhpArrayAdapter $arrayPool; + + protected function tearDown(): void + { + parent::tearDown(); + + if (isset($this->arrayPool)) { + $this->arrayPool->clear(); + unset($this->arrayPool); + } + } + + private function getArrayPool(string $file): PhpArrayAdapter + { + return $this->arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + } + /** * @dataProvider loaderProvider */ @@ -34,7 +51,7 @@ public function testWarmUp(array $loaders) $this->assertFileExists($file); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Person')->isHit()); $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); @@ -56,7 +73,7 @@ public function testWarmUpAbsoluteFilePath(array $loaders) $this->assertFileExists($file); $this->assertFileDoesNotExist($cacheDir.'/cache-serializer.php'); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Person')->isHit()); $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); @@ -75,10 +92,10 @@ public function testWarmUpWithoutBuildDir(array $loaders) $this->assertFileDoesNotExist($file); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); - $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Person')->isHit()); - $this->assertTrue($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); + $this->assertFalse($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Person')->isHit()); + $this->assertFalse($arrayPool->getItem('Symfony_Bundle_FrameworkBundle_Tests_Fixtures_Serialization_Author')->isHit()); } public static function loaderProvider(): array diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php index af0bb1b50d3dd..01d70d3a19262 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ValidatorCacheWarmerTest.php @@ -20,6 +20,23 @@ class ValidatorCacheWarmerTest extends TestCase { + private PhpArrayAdapter $arrayPool; + + protected function tearDown(): void + { + parent::tearDown(); + + if (isset($this->arrayPool)) { + $this->arrayPool->clear(); + unset($this->arrayPool); + } + } + + private function getArrayPool(string $file): PhpArrayAdapter + { + return $this->arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + } + public function testWarmUp() { $validatorBuilder = new ValidatorBuilder(); @@ -36,7 +53,7 @@ public function testWarmUp() $this->assertFileExists($file); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Person')->isHit()); $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Author')->isHit()); @@ -61,7 +78,7 @@ public function testWarmUpAbsoluteFilePath() $this->assertFileExists($file); $this->assertFileDoesNotExist($cacheDir.'/cache-validator.php'); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Person')->isHit()); $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Author')->isHit()); @@ -83,10 +100,10 @@ public function testWarmUpWithoutBuilDir() $this->assertFileDoesNotExist($file); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); - $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Person')->isHit()); - $this->assertTrue($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Author')->isHit()); + $this->assertFalse($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Person')->isHit()); + $this->assertFalse($arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Author')->isHit()); } public function testWarmUpWithAnnotations() @@ -103,7 +120,7 @@ public function testWarmUpWithAnnotations() $this->assertFileExists($file); - $arrayPool = new PhpArrayAdapter($file, new NullAdapter()); + $arrayPool = $this->getArrayPool($file); $item = $arrayPool->getItem('Symfony.Bundle.FrameworkBundle.Tests.Fixtures.Validation.Category'); $this->assertTrue($item->isHit()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index 5f5fc5ca51ecb..2024cb8f77082 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -236,7 +236,7 @@ public function testFile() $controller = $this->createController(); $controller->setContainer($container); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $response = $controller->file(new File(__FILE__)); $this->assertInstanceOf(BinaryFileResponse::class, $response); $this->assertSame(200, $response->getStatusCode()); @@ -251,7 +251,7 @@ public function testFileAsInline() { $controller = $this->createController(); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $response = $controller->file(new File(__FILE__), null, ResponseHeaderBag::DISPOSITION_INLINE); $this->assertInstanceOf(BinaryFileResponse::class, $response); @@ -267,7 +267,7 @@ public function testFileWithOwnFileName() { $controller = $this->createController(); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $fileName = 'test.php'; $response = $controller->file(new File(__FILE__), $fileName); @@ -284,7 +284,7 @@ public function testFileWithOwnFileNameAsInline() { $controller = $this->createController(); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $fileName = 'test.php'; $response = $controller->file(new File(__FILE__), $fileName, ResponseHeaderBag::DISPOSITION_INLINE); @@ -301,7 +301,7 @@ public function testFileFromPath() { $controller = $this->createController(); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $response = $controller->file(__FILE__); $this->assertInstanceOf(BinaryFileResponse::class, $response); @@ -317,7 +317,7 @@ public function testFileFromPathWithCustomizedFileName() { $controller = $this->createController(); - /* @var BinaryFileResponse $response */ + /** @var BinaryFileResponse $response */ $response = $controller->file(__FILE__, 'test.php'); $this->assertInstanceOf(BinaryFileResponse::class, $response); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php index 65826f6987702..c4f67c2f12ebe 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php @@ -440,10 +440,10 @@ public function testValidatorEmailValidationMode(string $mode) $this->createContainerFromClosure(function (ContainerBuilder $container) use ($mode) { $container->loadFromExtension('framework', [ - 'annotations' => false, - 'http_method_override' => false, - 'handle_all_throwables' => true, - 'php_errors' => ['log' => true], + 'annotations' => false, + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => ['log' => true], 'validation' => [ 'email_validation_mode' => $mode, ], diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Messenger/DummyCommand.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Messenger/DummyCommand.php new file mode 100644 index 0000000000000..c8f800850bee3 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Messenger/DummyCommand.php @@ -0,0 +1,30 @@ +addArgument('dummy-argument', InputArgument::OPTIONAL); + } + + public function execute(InputInterface $input, ?OutputInterface $output = null): int + { + self::$calls[__FUNCTION__][] = $input->getArgument('dummy-argument'); + + return Command::SUCCESS; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php index 0dcfeaeba5ce2..4848976aede71 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; +use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -216,15 +217,14 @@ public static function mapQueryStringProvider(): iterable /** * @dataProvider mapRequestPayloadProvider */ - public function testMapRequestPayload(string $uri, string $format, array $parameters, ?string $content, string $expectedResponse, int $expectedStatusCode) + public function testMapRequestPayload(string $uri, string $format, array $parameters, ?string $content, callable $responseAssertion, int $expectedStatusCode) { $client = self::createClient(['test_case' => 'ApiAttributesTest']); - [$acceptHeader, $assertion] = [ - 'html' => ['text/html', self::assertStringContainsString(...)], - 'json' => ['application/json', self::assertJsonStringEqualsJsonString(...)], - 'xml' => ['text/xml', self::assertXmlStringEqualsXmlString(...)], - 'dummy' => ['application/dummy', self::assertStringContainsString(...)], + $acceptHeader = [ + 'json' => 'application/json', + 'xml' => 'text/xml', + 'dummy' => 'application/dummy', ][$format]; $client->request( @@ -238,12 +238,7 @@ public function testMapRequestPayload(string $uri, string $format, array $parame $response = $client->getResponse(); $responseContent = $response->getContent(); - - if ($expectedResponse) { - $assertion($expectedResponse, $responseContent); - } else { - self::assertSame('', $responseContent); - } + $responseAssertion($responseContent); self::assertSame($expectedStatusCode, $response->getStatusCode()); } @@ -255,7 +250,9 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => [], 'content' => '', - 'expectedResponse' => '', + 'responseAssertion' => static function (string $response) { + self::assertSame('', $response); + }, 'expectedStatusCode' => 204, ]; @@ -269,12 +266,16 @@ public static function mapRequestPayloadProvider(): iterable "approved": false } JSON, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -288,12 +289,16 @@ public static function mapRequestPayloadProvider(): iterable true XML, - 'expectedResponse' => <<<'XML' - - Hello everyone! - 1 - - XML, + 'responseAssertion' => static function (string $response) { + self::assertXmlStringEqualsXmlString(<<<'XML' + + Hello everyone! + 1 + + XML, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -302,12 +307,16 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -321,14 +330,18 @@ public static function mapRequestPayloadProvider(): iterable "approved": false, } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title": "An error occurred", - "status": 400, - "detail": "Bad Request" - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 400, + "detail": "Bad Request" + } + JSON, + $response + ); + }, 'expectedStatusCode' => 400, ]; @@ -337,7 +350,9 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'dummy', 'parameters' => [], 'content' => 'Hello', - 'expectedResponse' => '415 Unsupported Media Type', + 'responseAssertion' => static function (string $response) { + self::assertStringContainsString('415 Unsupported Media Type', $response); + }, 'expectedStatusCode' => 415, ]; @@ -351,24 +366,28 @@ public static function mapRequestPayloadProvider(): iterable "approved": "string instead of bool" } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "approved: This value should be of type bool.", - "violations": [ - { - "propertyPath": "approved", - "title": "This value should be of type bool.", - "template": "This value should be of type {{ type }}.", - "parameters": { - "{{ type }}": "bool" + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "type": "https:\/\/symfony.com\/errors\/validation", + "title": "Validation Failed", + "status": 422, + "detail": "approved: This value should be of type bool.", + "violations": [ + { + "propertyPath": "approved", + "title": "This value should be of type bool.", + "template": "This value should be of type {{ type }}.", + "parameters": { + "{{ type }}": "bool" + } } - } - ] - } - JSON, + ] + } + JSON, + $response + ); + }, 'expectedStatusCode' => 422, ]; @@ -382,36 +401,20 @@ public static function mapRequestPayloadProvider(): iterable "approved": true } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; @@ -425,26 +428,16 @@ public static function mapRequestPayloadProvider(): iterable false XML, - 'expectedResponse' => <<<'XML' - - - https://symfony.com/errors/validation - Validation Failed - 422 - comment: This value is too short. It should have 10 characters or more. - - comment - This value is too short. It should have 10 characters or more. - - - "H" - 10 - 1 - - urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 - - - XML, + 'responseAssertion' => static function (string $response) { + $crawler = new Crawler($response); + + self::assertSame('https://symfony.com/errors/validation', $crawler->filterXPath('response/type')->text()); + self::assertSame('Validation Failed', $crawler->filterXPath('response/title')->text()); + self::assertSame('422', $crawler->filterXPath('response/status')->text()); + self::assertSame('comment: This value is too short. It should have 10 characters or more.', $crawler->filterXPath('response/detail')->text()); + self::assertCount(1, $crawler->filterXPath('response/violations')); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $crawler->filterXPath('response/violations/type')->text()); + }, 'expectedStatusCode' => 422, ]; @@ -453,36 +446,20 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; @@ -491,12 +468,16 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => [], 'content' => '', - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -510,12 +491,16 @@ public static function mapRequestPayloadProvider(): iterable "approved": false } JSON, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -529,12 +514,16 @@ public static function mapRequestPayloadProvider(): iterable true XML, - 'expectedResponse' => <<<'XML' - - Hello everyone! - 1 - - XML, + 'responseAssertion' => static function (string $response) { + self::assertXmlStringEqualsXmlString(<<<'XML' + + Hello everyone! + 1 + + XML, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -543,12 +532,16 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -562,14 +555,18 @@ public static function mapRequestPayloadProvider(): iterable "approved": false, } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title": "An error occurred", - "status": 400, - "detail": "Bad Request" - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 400, + "detail": "Bad Request" + } + JSON, + $response + ); + }, 'expectedStatusCode' => 400, ]; @@ -578,7 +575,9 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'dummy', 'parameters' => [], 'content' => 'Hello', - 'expectedResponse' => '415 Unsupported Media Type', + 'responseAssertion' => static function (string $response) { + self::assertStringContainsString('415 Unsupported Media Type', $response); + }, 'expectedStatusCode' => 415, ]; @@ -592,24 +591,19 @@ public static function mapRequestPayloadProvider(): iterable "approved": "string instead of bool" } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "approved: This value should be of type bool.", - "violations": [ - { - "propertyPath": "approved", - "title": "This value should be of type bool.", - "template": "This value should be of type {{ type }}.", - "parameters": { - "{{ type }}": "bool" - } - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame('approved: This value should be of type bool.', $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(1, $json['violations']); + self::assertSame('approved', $json['violations'][0]['propertyPath'] ?? null); +}, 'expectedStatusCode' => 422, ]; @@ -623,36 +617,20 @@ public static function mapRequestPayloadProvider(): iterable "approved": true } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; @@ -666,26 +644,16 @@ public static function mapRequestPayloadProvider(): iterable false XML, - 'expectedResponse' => <<<'XML' - - - https://symfony.com/errors/validation - Validation Failed - 422 - comment: This value is too short. It should have 10 characters or more. - - comment - This value is too short. It should have 10 characters or more. - - - "H" - 10 - 1 - - urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 - - - XML, + 'responseAssertion' => static function (string $response) { + $crawler = new Crawler($response); + + self::assertSame('https://symfony.com/errors/validation', $crawler->filterXPath('response/type')->text()); + self::assertSame('Validation Failed', $crawler->filterXPath('response/title')->text()); + self::assertSame('422', $crawler->filterXPath('response/status')->text()); + self::assertSame('comment: This value is too short. It should have 10 characters or more.', $crawler->filterXPath('response/detail')->text()); + self::assertCount(1, $crawler->filterXPath('response/violations')); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $crawler->filterXPath('response/violations/type')->text()); + }, 'expectedStatusCode' => 422, ]; @@ -694,56 +662,41 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; - $expectedStatusCode = 400; - $expectedResponse = <<<'JSON' - { - "type":"https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title":"An error occurred", - "status":400, - "detail":"Bad Request" - } - JSON; - yield 'empty request mapping non-nullable attribute without default value' => [ 'uri' => '/map-request-to-non-nullable-attribute-without-default-value.json', 'format' => 'json', 'parameters' => [], 'content' => '', - 'expectedResponse' => $expectedResponse, - 'expectedStatusCode' => $expectedStatusCode, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "type":"https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title":"An error occurred", + "status":400, + "detail":"Bad Request" + } + JSON, + $response + ); + }, + 'expectedStatusCode' => 400, ]; yield 'valid request with json content mapping non-nullable attribute without default value' => [ @@ -756,12 +709,16 @@ public static function mapRequestPayloadProvider(): iterable "approved": false } JSON, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -775,12 +732,16 @@ public static function mapRequestPayloadProvider(): iterable true XML, - 'expectedResponse' => <<<'XML' - - Hello everyone! - 1 - - XML, + 'responseAssertion' => static function (string $response) { + self::assertXmlStringEqualsXmlString(<<<'XML' + + Hello everyone! + 1 + + XML, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -789,12 +750,16 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => 'Hello everyone!', 'approved' => '0'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "comment": "Hello everyone!", - "approved": false - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "comment": "Hello everyone!", + "approved": false + } + JSON, + $response + ); + }, 'expectedStatusCode' => 200, ]; @@ -808,14 +773,18 @@ public static function mapRequestPayloadProvider(): iterable "approved": false, } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", - "title": "An error occurred", - "status": 400, - "detail": "Bad Request" - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJsonStringEqualsJsonString(<<<'JSON' + { + "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10", + "title": "An error occurred", + "status": 400, + "detail": "Bad Request" + } + JSON, + $response + ); + }, 'expectedStatusCode' => 400, ]; @@ -824,7 +793,9 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'dummy', 'parameters' => [], 'content' => 'Hello', - 'expectedResponse' => '415 Unsupported Media Type', + 'responseAssertion' => static function (string $response) { + self::assertStringContainsString('415 Unsupported Media Type', $response); + }, 'expectedStatusCode' => 415, ]; @@ -838,24 +809,19 @@ public static function mapRequestPayloadProvider(): iterable "approved": "string instead of bool" } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "approved: This value should be of type bool.", - "violations": [ - { - "propertyPath": "approved", - "title": "This value should be of type bool.", - "template": "This value should be of type {{ type }}.", - "parameters": { - "{{ type }}": "bool" - } - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame('approved: This value should be of type bool.', $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(1, $json['violations']); + self::assertSame('approved', $json['violations'][0]['propertyPath'] ?? null); + }, 'expectedStatusCode' => 422, ]; @@ -869,36 +835,20 @@ public static function mapRequestPayloadProvider(): iterable "approved": true } JSON, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; @@ -912,26 +862,16 @@ public static function mapRequestPayloadProvider(): iterable false XML, - 'expectedResponse' => <<<'XML' - - - https://symfony.com/errors/validation - Validation Failed - 422 - comment: This value is too short. It should have 10 characters or more. - - comment - This value is too short. It should have 10 characters or more. - - - "H" - 10 - 1 - - urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 - - - XML, + 'responseAssertion' => static function (string $response) { + $crawler = new Crawler($response); + + self::assertSame('https://symfony.com/errors/validation', $crawler->filterXPath('response/type')->text()); + self::assertSame('Validation Failed', $crawler->filterXPath('response/title')->text()); + self::assertSame('422', $crawler->filterXPath('response/status')->text()); + self::assertSame('comment: This value is too short. It should have 10 characters or more.', $crawler->filterXPath('response/detail')->text()); + self::assertCount(1, $crawler->filterXPath('response/violations')); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $crawler->filterXPath('response/violations/type')->text()); + }, 'expectedStatusCode' => 422, ]; @@ -940,36 +880,20 @@ public static function mapRequestPayloadProvider(): iterable 'format' => 'json', 'parameters' => ['comment' => '', 'approved' => '1'], 'content' => null, - 'expectedResponse' => <<<'JSON' - { - "type": "https:\/\/symfony.com\/errors\/validation", - "title": "Validation Failed", - "status": 422, - "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", - "violations": [ - { - "propertyPath": "comment", - "title": "This value should not be blank.", - "template": "This value should not be blank.", - "parameters": { - "{{ value }}": "\"\"" - }, - "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3" - }, - { - "propertyPath": "comment", - "title": "This value is too short. It should have 10 characters or more.", - "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.", - "parameters": { - "{{ value }}": "\"\"", - "{{ limit }}": "10", - "{{ value_length }}": "0" - }, - "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45" - } - ] - } - JSON, + 'responseAssertion' => static function (string $response) { + self::assertJson($response); + + $json = json_decode($response, true); + + self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null); + self::assertSame('Validation Failed', $json['title'] ?? null); + self::assertSame(422, $json['status'] ?? null); + self::assertSame("comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.", $json['detail'] ?? null); + self::assertIsArray($json['violations'] ?? null); + self::assertCount(2, $json['violations']); + self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null); + self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null); + }, 'expectedStatusCode' => 422, ]; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php new file mode 100644 index 0000000000000..f0b6b4bd57b07 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ContainerLintCommandTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; + +/** + * @group functional + */ +class ContainerLintCommandTest extends AbstractWebTestCase +{ + private Application $application; + + /** + * @dataProvider containerLintProvider + */ + public function testLintContainer(string $configFile, bool $resolveEnvVars, int $expectedExitCode, string $expectedOutput) + { + $kernel = static::createKernel([ + 'test_case' => 'ContainerLint', + 'root_config' => $configFile, + 'debug' => true, + ]); + $this->application = new Application($kernel); + + $tester = $this->createCommandTester(); + $exitCode = $tester->execute(['--resolve-env-vars' => $resolveEnvVars]); + + $this->assertSame($expectedExitCode, $exitCode); + $this->assertStringContainsString($expectedOutput, $tester->getDisplay()); + } + + public static function containerLintProvider(): array + { + return [ + ['escaped_percent.yml', false, 0, 'The container was linted successfully'], + ['missing_env_var.yml', false, 0, 'The container was linted successfully'], + ['missing_env_var.yml', true, 1, 'Environment variable not found: "BAR"'], + ]; + } + + private function createCommandTester(): CommandTester + { + return new CommandTester($this->application->get('lint:container')); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SchedulerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SchedulerTest.php index 99776e8223e9d..537493a5580b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SchedulerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SchedulerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\BarMessage; +use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyCommand; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummySchedule; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyTask; use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\FooMessage; @@ -88,6 +89,29 @@ public function testAutoconfiguredScheduler() $this->assertSame([['5', 6], ['7', 8]], $calls['attributesOnMethod']); } + public function testAutoconfiguredSchedulerCommand() + { + $container = self::getContainer(); + $container->set('clock', $clock = new MockClock('2023-10-26T08:59:59Z')); + + $this->assertTrue($container->get('receivers')->has('scheduler_dummy_command')); + $this->assertInstanceOf(SchedulerTransport::class, $cron = $container->get('receivers')->get('scheduler_dummy_command')); + $bus = $container->get(MessageBusInterface::class); + + $getCalls = static function (float $sleep) use ($clock, $cron, $bus) { + DummyCommand::$calls = []; + $clock->sleep($sleep); + foreach ($cron->get() as $message) { + $bus->dispatch($message->with(new ReceivedStamp('scheduler_dummy_command'))); + } + + return DummyCommand::$calls; + }; + + $this->assertSame([], $getCalls(0)); + $this->assertSame(['execute' => [0 => null, 1 => 'test']], $getCalls(1)); + } + public function testSchedulerWithCustomTransport() { $container = self::getContainer(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/bundles.php new file mode 100644 index 0000000000000..15ff182c6fed5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; + +return [ + new FrameworkBundle(), + new TestBundle(), +]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/escaped_percent.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/escaped_percent.yml new file mode 100644 index 0000000000000..f5554e116546c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/escaped_percent.yml @@ -0,0 +1,5 @@ +imports: + - { resource: ../config/default.yml } + +parameters: + percent: '%%foo%%' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/missing_env_var.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/missing_env_var.yml new file mode 100644 index 0000000000000..33ac97df47c3d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerLint/missing_env_var.yml @@ -0,0 +1,5 @@ +imports: + - { resource: ../config/default.yml } + +parameters: + foo: '%env(BAR)%' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Scheduler/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Scheduler/config.yml index bd1cb6516b260..f5bc14ec46dc0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Scheduler/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Scheduler/config.yml @@ -16,6 +16,9 @@ services: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyTaskWithCustomReceiver: autoconfigure: true + Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyCommand: + autoconfigure: true + clock: synthetic: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php index 5c7161124bda5..159dd21eb2690 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Psr\Log\NullLogger; use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; @@ -186,27 +185,3 @@ public function testDefaultKernel() $this->assertSame('OK', $response->getContent()); } } - -abstract class MinimalKernel extends Kernel -{ - use MicroKernelTrait; - - private string $cacheDir; - - public function __construct(string $cacheDir) - { - parent::__construct('test', false); - - $this->cacheDir = sys_get_temp_dir().'/'.$cacheDir; - } - - public function getCacheDir(): string - { - return $this->cacheDir; - } - - public function getLogDir(): string - { - return $this->cacheDir; - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MinimalKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MinimalKernel.php new file mode 100644 index 0000000000000..df2c97e6a0be8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MinimalKernel.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; + +use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; +use Symfony\Component\HttpKernel\Kernel; + +abstract class MinimalKernel extends Kernel +{ + use MicroKernelTrait; + + private string $cacheDir; + + public function __construct(string $cacheDir) + { + parent::__construct('test', false); + + $this->cacheDir = sys_get_temp_dir().'/'.$cacheDir; + } + + public function getCacheDir(): string + { + return $this->cacheDir; + } + + public function getLogDir(): string + { + return $this->cacheDir; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 15a9496d11067..a00bac1c3a9b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -65,7 +65,7 @@ "symfony/string": "^6.4|^7.0", "symfony/translation": "^7.3", "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1", + "symfony/type-info": "^7.1.8", "symfony/validator": "^6.4|^7.0", "symfony/workflow": "^7.3", "symfony/yaml": "^6.4|^7.0", diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index d0f3549ab8f09..8607e45a262e2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -986,7 +986,7 @@ public function checkPreAuth(UserInterface $user): void { } - public function checkPostAuth(UserInterface $user): void + public function checkPostAuth(UserInterface $user, ?TokenInterface $token = null): void { } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php index 82a444ef10358..9a126ae328e08 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/SecurityTest.php @@ -154,7 +154,7 @@ public function testLogin() ->method('getProvidedServices') ->willReturn([ 'security.authenticator.custom.dev' => $authenticator, - 'security.authenticator.remember_me.main' => $authenticator + 'security.authenticator.remember_me.main' => $authenticator, ]) ; $firewallAuthenticatorLocator @@ -287,7 +287,7 @@ public function testLoginFailsWhenTooManyAuthenticatorsFound() ->method('getProvidedServices') ->willReturn([ 'security.authenticator.custom.main' => $authenticator, - 'security.authenticator.other.main' => $authenticator + 'security.authenticator.other.main' => $authenticator, ]) ; diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 418172956391b..ccd546b93ca70 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -30,7 +30,6 @@ use Twig\Attribute\AsTwigFilter; use Twig\Attribute\AsTwigFunction; use Twig\Attribute\AsTwigTest; -use Twig\Cache\FilesystemCache; use Twig\Environment; use Twig\Extension\ExtensionInterface; use Twig\Extension\RuntimeExtensionInterface; diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php index 0105c71775903..3ea59d07fa469 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.php @@ -40,13 +40,13 @@ use Twig\Cache\FilesystemCache; use Twig\Cache\ReadOnlyFilesystemCache; use Twig\Environment; +use Twig\ExpressionParser\Infix\BinaryOperatorExpressionParser; use Twig\Extension\CoreExtension; use Twig\Extension\DebugExtension; use Twig\Extension\EscaperExtension; use Twig\Extension\OptimizerExtension; use Twig\Extension\StagingExtension; use Twig\ExtensionSet; -use Twig\ExpressionParser\Infix\BinaryOperatorExpressionParser; use Twig\Loader\ChainLoader; use Twig\Loader\FilesystemLoader; use Twig\Profiler\Profile; diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 086a4cdd6e1e8..ddc489e783671 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -105,7 +105,7 @@ public function testLoadFullConfiguration(string $format, ?string $buildDir) $this->assertEquals('ISO-8859-1', $options['charset'], '->load() sets the charset option'); $this->assertTrue($options['debug'], '->load() sets the debug option'); $this->assertTrue($options['strict_variables'], '->load() sets the strict_variables option'); - $this->assertEquals($buildDir !== null ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets the cache option'); + $this->assertEquals(null !== $buildDir ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets the cache option'); } /** @@ -156,7 +156,7 @@ public function testLoadProdCacheConfiguration(string $format, ?string $buildDir // Twig options $options = $container->getDefinition('twig')->getArgument(1); - $this->assertEquals($buildDir !== null ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets cache option to CacheChain reference'); + $this->assertEquals(null !== $buildDir ? new Reference('twig.template_cache.chain') : '%kernel.cache_dir%/twig', $options['cache'], '->load() sets cache option to CacheChain reference'); } /** @@ -308,7 +308,6 @@ public static function getFormatsAndBuildDir(): array ]; } - /** * @dataProvider stopwatchExtensionAvailabilityProvider */ diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php index 8b4e4555f36a0..32db815b16a37 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php @@ -90,9 +90,9 @@ public function registerContainerConfiguration(LoaderInterface $loader): void $kernel->boot(); } - /** * @before + * * @after */ #[Before, After] diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php index 332a5d6c3725e..299a1b02cf595 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/CodeExtension.php @@ -16,7 +16,7 @@ use Twig\TwigFilter; /** - * Twig extension relate to PHP code and used by the profiler and the default exception templates. + * Twig extension related to PHP code and used by the profiler and the default exception templates. * * This extension should only be used for debugging tools code * that is never executed in a production environment. @@ -119,39 +119,85 @@ public function formatArgsAsText(array $args): string */ public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?string { - if (is_file($file) && is_readable($file)) { - // highlight_file could throw warnings - // see https://bugs.php.net/25725 - $code = @highlight_file($file, true); - if (\PHP_VERSION_ID >= 80300) { - // remove main pre/code tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline span tags - $code = preg_replace_callback('#]++)>((?:[^<\\n]*+\\n)++[^<]*+)#', function ($m) { - return "".str_replace("\n", "\n", $m[2]).''; - }, $code); - $content = explode("\n", $code); - } else { - // remove main code/span tags - $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline spans - $code = preg_replace_callback('#]++)>((?:[^<]*+
)++[^<]*+)
#', fn ($m) => "".str_replace('
', "

", $m[2]).'', $code); - $content = explode('
', $code); - } + if (!is_file($file) || !is_readable($file)) { + return null; + } + + $contents = file_get_contents($file); + + if (!str_contains($contents, ' $srcContext) { - $srcContext = \count($content); + $srcContext = \count($lines); } - for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { - $lines[] = ''.self::fixCodeMarkup($content[$i - 1]).''; - } + return $this->formatFileExcerpt( + $this->extractExcerptLines($lines, $line, $srcContext), + $line, + $srcContext + ); + } - return '
    '.implode("\n", $lines).'
'; + // highlight_string could throw warnings + // see https://bugs.php.net/25725 + $code = @highlight_string($contents, true); + + if (\PHP_VERSION_ID >= 80300) { + // remove main pre/code tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline span tags + $code = preg_replace_callback( + '#]++)>((?:[^<\\n]*+\\n)++[^<]*+)#', + static fn (array $m): string => "".str_replace("\n", "\n", $m[2]).'', + $code + ); + $lines = explode("\n", $code); + } else { + // remove main code/span tags + $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); + // split multiline spans + $code = preg_replace_callback( + '#]++)>((?:[^<]*+
)++[^<]*+)
#', + static fn (array $m): string => "".str_replace('
', "

", $m[2]).'', + $code + ); + $lines = explode('
', $code); } - return null; + if (0 > $srcContext) { + $srcContext = \count($lines); + } + + return $this->formatFileExcerpt( + array_map( + self::fixCodeMarkup(...), + $this->extractExcerptLines($lines, $line, $srcContext), + ), + $line, + $srcContext + ); + } + + private function extractExcerptLines(array $lines, int $selectedLine, int $srcContext): array + { + return \array_slice( + $lines, + max($selectedLine - $srcContext, 0), + min($srcContext * 2 + 1, \count($lines) - $selectedLine + $srcContext), + true + ); + } + + private function formatFileExcerpt(array $lines, int $selectedLine, int $srcContext): string + { + $start = max($selectedLine - $srcContext, 1); + + return "
    ".implode("\n", array_map( + static fn (string $line, int $num): string => '{$line}", + $lines, + array_keys($lines), + )).'
'; } /** @@ -241,7 +287,7 @@ protected static function fixCodeMarkup(string $line): string // missing tag at the end of line $opening = strpos($line, ''); - if (false !== $opening && (false === $closing || $closing > $opening)) { + if (false !== $opening && (false === $closing || $closing < $opening)) { $line .= ''; } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 5adfd27796acf..dd9527d24b0ab 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -415,11 +415,7 @@ renderAjaxRequests: renderAjaxRequests, getSfwdt: function(token) { - if (!this.sfwdt) { - this.sfwdt = document.getElementById('sfwdt' + token); - } - - return this.sfwdt; + return document.getElementById('sfwdt' + token); }, load: function(selector, url, onSuccess, onError, options) { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.json b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.json new file mode 100644 index 0000000000000..56cc557387321 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.json @@ -0,0 +1,4 @@ +[ + "Hello", + "World!" +] diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.php new file mode 100644 index 0000000000000..4d7bf8fdf167e --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Fixtures/hello_world.php @@ -0,0 +1,4 @@ +assertEquals($expected, $this->render($template)); } + /** + * @dataProvider fileExcerptIntegrationProvider + */ + public function testFileExcerptIntegration(string $expected, array $data) + { + $template = <<<'TWIG' +{{ file_path|file_excerpt(line, src_context) }} +TWIG; + $html = $this->render($template, $data); + + // highlight_file function output changed sing PHP 8.3 + // see https://github.com/php/php-src/blob/e2667f17bc24e3cd200bb3eda457f566f1f77f8f/UPGRADING#L239-L242 + if (\PHP_VERSION_ID < 80300) { + $html = str_replace(' ', ' ', $html); + } + + $html = html_entity_decode($html); + + $this->assertEquals($expected, $html); + } + + public static function fileExcerptIntegrationProvider() + { + $fixturesPath = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures'; + + yield 'php file' => [ + 'expected' => <<<'HTML' +
  1. +
  2. +
  3. echo 'Hello';
  4. +
  5. echo 'World!';
  6. +
+HTML, + 'data' => [ + 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', + 'line' => 0, + 'src_context' => 3, + ], + ]; + + yield 'php file with selected line and no source context' => [ + 'expected' => <<<'HTML' +
  1. +
  2. +
  3. echo 'Hello';
  4. +
  5. echo 'World!';
  6. +
+HTML, + 'data' => [ + 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', + 'line' => 1, + 'src_context' => -1, + ], + ]; + + yield 'php file excerpt with selected line and custom source context' => [ + 'expected' => <<<'HTML' +
  1. echo 'Hello';
  2. +
  3. echo 'World!';
  4. +
+HTML, + 'data' => [ + 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', + 'line' => 3, + 'src_context' => 1, + ], + ]; + + yield 'php file excerpt with out of bound selected line' => [ + 'expected' => <<<'HTML' +
    +HTML, + 'data' => [ + 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.php', + 'line' => 100, + 'src_context' => 1, + ], + ]; + + yield 'json file' => [ + 'expected' => <<<'HTML' +
    1. [
    2. +
    3. "Hello",
    4. +
    5. "World!"
    6. +
    7. ]
    8. +
    +HTML, + 'data' => [ + 'file_path' => $fixturesPath.\DIRECTORY_SEPARATOR.'hello_world.json', + 'line' => 0, + 'src_context' => 3, + ], + ]; + } + public function testFormatFileFromTextIntegration() { $template = <<<'TWIG' diff --git a/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php b/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php index 7531221a8e5ee..6980e661500c3 100644 --- a/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php +++ b/src/Symfony/Component/AssetMapper/Compiler/Parser/JavascriptSequenceParser.php @@ -138,20 +138,21 @@ public function parseUntil(int $position): void while (false !== $endPos = strpos($this->content, $matchChar, $endPos)) { $backslashes = 0; $i = $endPos - 1; - while ($i >= 0 && $this->content[$i] === '\\') { - $backslashes++; - $i--; + while ($i >= 0 && '\\' === $this->content[$i]) { + ++$backslashes; + --$i; } if (0 === $backslashes % 2) { break; } - $endPos++; + ++$endPos; } if (false === $endPos) { $this->endsWithSequence(self::STATE_STRING, $position); + return; } diff --git a/src/Symfony/Component/AssetMapper/ImportMap/Resolver/JsDelivrEsmResolver.php b/src/Symfony/Component/AssetMapper/ImportMap/Resolver/JsDelivrEsmResolver.php index b88f0e792d44f..e0de404e77094 100644 --- a/src/Symfony/Component/AssetMapper/ImportMap/Resolver/JsDelivrEsmResolver.php +++ b/src/Symfony/Component/AssetMapper/ImportMap/Resolver/JsDelivrEsmResolver.php @@ -196,7 +196,7 @@ public function downloadPackages(array $importMapEntries, ?callable $progressCal $dependencies = []; $extraFiles = []; - /* @var ImportMapEntry $entry */ + /** @var ImportMapEntry $entry */ $contents[$package] = [ 'content' => $this->makeImportsBare($response->getContent(), $dependencies, $extraFiles, $entry->type, $entry->getPackagePathString()), 'dependencies' => $dependencies, diff --git a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php index c2805f937de8b..e6084fc7c1e87 100644 --- a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php @@ -248,7 +248,7 @@ public function testUpdateAll() ->method('resolvePackages') ->with($this->callback(function ($packages) { $this->assertInstanceOf(PackageRequireOptions::class, $packages[0]); - /* @var PackageRequireOptions[] $packages */ + /** @var PackageRequireOptions[] $packages */ $this->assertCount(2, $packages); $this->assertSame('lodash', $packages[0]->packageModuleSpecifier); diff --git a/src/Symfony/Component/BrowserKit/AbstractBrowser.php b/src/Symfony/Component/BrowserKit/AbstractBrowser.php index 1269fcb69e8cb..68cc417e41a0f 100644 --- a/src/Symfony/Component/BrowserKit/AbstractBrowser.php +++ b/src/Symfony/Component/BrowserKit/AbstractBrowser.php @@ -461,10 +461,10 @@ abstract protected function doRequest(object $request); /** * Returns the script to execute when the request must be insulated. * - * @psalm-param TRequest $request - * * @param object $request An origin request instance * + * @psalm-param TRequest $request + * * @return string * * @throws LogicException When this abstract class is not implemented diff --git a/src/Symfony/Component/Cache/Tests/Traits/RedisProxiesTest.php b/src/Symfony/Component/Cache/Tests/Traits/RedisProxiesTest.php index 50f784da162be..162ac495e8d35 100644 --- a/src/Symfony/Component/Cache/Tests/Traits/RedisProxiesTest.php +++ b/src/Symfony/Component/Cache/Tests/Traits/RedisProxiesTest.php @@ -88,12 +88,12 @@ public function testRelayProxy() $expectedMethods = []; foreach ((new \ReflectionClass(RelayProxy::class))->getMethods() as $method) { - if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name) || $method->isStatic()) { + if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name) || $method->isInternal()) { continue; } $return = '__construct' === $method->name || $method->getReturnType() instanceof \ReflectionNamedType && 'void' === (string) $method->getReturnType() ? '' : 'return '; - $expectedMethods[$method->name] = "\n ".ProxyHelper::exportSignature($method, false, $args)."\n".<<name] = "\n ".ProxyHelper::exportSignature($method, true, $args)."\n".<<initializeLazyObject()->{$method->name}({$args}); } @@ -102,7 +102,7 @@ public function testRelayProxy() } foreach ((new \ReflectionClass(Relay::class))->getMethods() as $method) { - if ('reset' === $method->name || method_exists(RedisProxyTrait::class, $method->name) || $method->isStatic()) { + if ('__destruct' === $method->name || 'reset' === $method->name || $method->isStatic()) { continue; } $return = '__construct' === $method->name || $method->getReturnType() instanceof \ReflectionNamedType && 'void' === (string) $method->getReturnType() ? '' : 'return '; diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 19b4b911fb451..827a4cd0720b2 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -498,7 +498,7 @@ protected function doFetch(array $ids): iterable $result = []; - if ($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) { + if (($this->redis instanceof \Predis\ClientInterface && ($this->redis->getConnection() instanceof ClusterInterface || $this->redis->getConnection() instanceof Predis2ClusterInterface)) || $this->redis instanceof RelayCluster) { $values = $this->pipeline(function () use ($ids) { foreach ($ids as $id) { yield 'get' => [$id]; diff --git a/src/Symfony/Component/Cache/Traits/Relay/BgsaveTrait.php b/src/Symfony/Component/Cache/Traits/Relay/BgsaveTrait.php index 367f82f7bb2b6..f5cddcb85225f 100644 --- a/src/Symfony/Component/Cache/Traits/Relay/BgsaveTrait.php +++ b/src/Symfony/Component/Cache/Traits/Relay/BgsaveTrait.php @@ -19,7 +19,7 @@ trait BgsaveTrait { public function bgsave($arg = null): \Relay\Relay|bool { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args()); + return $this->initializeLazyObject()->bgsave(...\func_get_args()); } } } else { @@ -30,7 +30,7 @@ trait BgsaveTrait { public function bgsave($schedule = false): \Relay\Relay|bool { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args()); + return $this->initializeLazyObject()->bgsave(...\func_get_args()); } } } diff --git a/src/Symfony/Component/Cache/Traits/Relay/FtTrait.php b/src/Symfony/Component/Cache/Traits/Relay/FtTrait.php new file mode 100644 index 0000000000000..8accd79386cbc --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/Relay/FtTrait.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait FtTrait + { + public function ftAggregate($index, $query, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftAggregate(...\func_get_args()); + } + + public function ftAliasAdd($index, $alias): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftAliasAdd(...\func_get_args()); + } + + public function ftAliasDel($alias): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftAliasDel(...\func_get_args()); + } + + public function ftAliasUpdate($index, $alias): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftAliasUpdate(...\func_get_args()); + } + + public function ftAlter($index, $schema, $skipinitialscan = false): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftAlter(...\func_get_args()); + } + + public function ftConfig($operation, $option, $value = null): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->ftConfig(...\func_get_args()); + } + + public function ftCreate($index, $schema, $options = null): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftCreate(...\func_get_args()); + } + + public function ftCursor($operation, $index, $cursor, $options = null): \Relay\Relay|array|bool + { + return $this->initializeLazyObject()->ftCursor(...\func_get_args()); + } + + public function ftDictAdd($dict, $term, ...$other_terms): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->ftDictAdd(...\func_get_args()); + } + + public function ftDictDel($dict, $term, ...$other_terms): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->ftDictDel(...\func_get_args()); + } + + public function ftDictDump($dict): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftDictDump(...\func_get_args()); + } + + public function ftDropIndex($index, $dd = false): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftDropIndex(...\func_get_args()); + } + + public function ftExplain($index, $query, $dialect = 0): \Relay\Relay|false|string + { + return $this->initializeLazyObject()->ftExplain(...\func_get_args()); + } + + public function ftExplainCli($index, $query, $dialect = 0): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftExplainCli(...\func_get_args()); + } + + public function ftInfo($index): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftInfo(...\func_get_args()); + } + + public function ftProfile($index, $command, $query, $limited = false): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftProfile(...\func_get_args()); + } + + public function ftSearch($index, $query, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftSearch(...\func_get_args()); + } + + public function ftSpellCheck($index, $query, $options = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftSpellCheck(...\func_get_args()); + } + + public function ftSynDump($index): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftSynDump(...\func_get_args()); + } + + public function ftSynUpdate($index, $synonym, $term_or_terms, $skipinitialscan = false): \Relay\Relay|bool + { + return $this->initializeLazyObject()->ftSynUpdate(...\func_get_args()); + } + + public function ftTagVals($index, $tag): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->ftTagVals(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait FtTrait + { + } +} diff --git a/src/Symfony/Component/Cache/Traits/Relay/GetWithMetaTrait.php b/src/Symfony/Component/Cache/Traits/Relay/GetWithMetaTrait.php new file mode 100644 index 0000000000000..79a75ede54ee8 --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/Relay/GetWithMetaTrait.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.10.1', '>=')) { + /** + * @internal + */ + trait GetWithMetaTrait + { + public function getWithMeta($key): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->getWithMeta(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GetWithMetaTrait + { + } +} diff --git a/src/Symfony/Component/Cache/Traits/Relay/IsTrackedTrait.php b/src/Symfony/Component/Cache/Traits/Relay/IsTrackedTrait.php new file mode 100644 index 0000000000000..28520802959bb --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/Relay/IsTrackedTrait.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.11.1', '>=')) { + /** + * @internal + */ + trait IsTrackedTrait + { + public function isTracked($key): bool + { + return $this->initializeLazyObject()->isTracked(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait IsTrackedTrait + { + } +} diff --git a/src/Symfony/Component/Cache/Traits/Relay/Relay11Trait.php b/src/Symfony/Component/Cache/Traits/Relay/Relay11Trait.php new file mode 100644 index 0000000000000..eeeeb456c330e --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/Relay/Relay11Trait.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.11.0', '>=')) { + /** + * @internal + */ + trait Relay11Trait + { + public function cmsIncrBy($key, $field, $value, ...$fields_and_falues): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->cmsIncrBy(...\func_get_args()); + } + + public function cmsInfo($key): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->cmsInfo(...\func_get_args()); + } + + public function cmsInitByDim($key, $width, $depth): \Relay\Relay|bool + { + return $this->initializeLazyObject()->cmsInitByDim(...\func_get_args()); + } + + public function cmsInitByProb($key, $error, $probability): \Relay\Relay|bool + { + return $this->initializeLazyObject()->cmsInitByProb(...\func_get_args()); + } + + public function cmsMerge($dstkey, $keys, $weights = []): \Relay\Relay|bool + { + return $this->initializeLazyObject()->cmsMerge(...\func_get_args()); + } + + public function cmsQuery($key, ...$fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->cmsQuery(...\func_get_args()); + } + + public function commandlog($subcmd, ...$args): \Relay\Relay|array|bool|int + { + return $this->initializeLazyObject()->commandlog(...\func_get_args()); + } + + public function hexpire($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hexpire(...\func_get_args()); + } + + public function hexpireat($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hexpireat(...\func_get_args()); + } + + public function hexpiretime($hash, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hexpiretime(...\func_get_args()); + } + + public function hgetdel($key, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hgetdel(...\func_get_args()); + } + + public function hgetex($hash, $fields, $expiry = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hgetex(...\func_get_args()); + } + + public function hpersist($hash, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hpersist(...\func_get_args()); + } + + public function hpexpire($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hpexpire(...\func_get_args()); + } + + public function hpexpireat($hash, $ttl, $fields, $mode = null): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hpexpireat(...\func_get_args()); + } + + public function hpexpiretime($hash, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hpexpiretime(...\func_get_args()); + } + + public function hpttl($hash, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->hpttl(...\func_get_args()); + } + + public function hsetex($key, $fields, $expiry = null): \Relay\Relay|false|int + { + return $this->initializeLazyObject()->hsetex(...\func_get_args()); + } + + public function httl($hash, $fields): \Relay\Relay|array|false + { + return $this->initializeLazyObject()->httl(...\func_get_args()); + } + + public function serverName(): false|string + { + return $this->initializeLazyObject()->serverName(...\func_get_args()); + } + + public function serverVersion(): false|string + { + return $this->initializeLazyObject()->serverVersion(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait Relay11Trait + { + } +} diff --git a/src/Symfony/Component/Cache/Traits/Relay/SwapdbTrait.php b/src/Symfony/Component/Cache/Traits/Relay/SwapdbTrait.php new file mode 100644 index 0000000000000..46cb2fec81d29 --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/Relay/SwapdbTrait.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait SwapdbTrait + { + public function swapdb($index1, $index2): \Relay\Relay|bool + { + return $this->initializeLazyObject()->swapdb(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait SwapdbTrait + { + } +} diff --git a/src/Symfony/Component/Cache/Traits/RelayClusterProxy.php b/src/Symfony/Component/Cache/Traits/RelayClusterProxy.php index fd5f08b5a4525..af524c8008131 100644 --- a/src/Symfony/Component/Cache/Traits/RelayClusterProxy.php +++ b/src/Symfony/Component/Cache/Traits/RelayClusterProxy.php @@ -31,13 +31,13 @@ class RelayClusterProxy extends Cluster implements ResetInterface, LazyObjectInt } public function __construct( - string|null $name, - array|null $seeds = null, + ?string $name, + ?array $seeds = null, int|float $connect_timeout = 0, int|float $command_timeout = 0, bool $persistent = false, #[\SensitiveParameter] mixed $auth = null, - array|null $context = null, + ?array $context = null, ) { $this->initializeLazyObject()->__construct(...\func_get_args()); } @@ -172,12 +172,12 @@ public function info(array|string $key_or_address, string ...$sections): Cluster return $this->initializeLazyObject()->info(...\func_get_args()); } - public function flushdb(array|string $key_or_address, bool|null $sync = null): Cluster|bool + public function flushdb(array|string $key_or_address, ?bool $sync = null): Cluster|bool { return $this->initializeLazyObject()->flushdb(...\func_get_args()); } - public function flushall(array|string $key_or_address, bool|null $sync = null): Cluster|bool + public function flushall(array|string $key_or_address, ?bool $sync = null): Cluster|bool { return $this->initializeLazyObject()->flushall(...\func_get_args()); } @@ -192,7 +192,7 @@ public function waitaof(array|string $key_or_address, int $numlocal, int $numrem return $this->initializeLazyObject()->waitaof(...\func_get_args()); } - public function restore(mixed $key, int $ttl, string $value, array|null $options = null): Cluster|bool + public function restore(mixed $key, int $ttl, string $value, ?array $options = null): Cluster|bool { return $this->initializeLazyObject()->restore(...\func_get_args()); } @@ -202,7 +202,7 @@ public function echo(array|string $key_or_address, string $message): Cluster|str return $this->initializeLazyObject()->echo(...\func_get_args()); } - public function ping(array|string $key_or_address, string|null $message = null): Cluster|bool|string + public function ping(array|string $key_or_address, ?string $message = null): Cluster|bool|string { return $this->initializeLazyObject()->ping(...\func_get_args()); } @@ -232,7 +232,7 @@ public function lastsave(array|string $key_or_address): Cluster|false|int return $this->initializeLazyObject()->lastsave(...\func_get_args()); } - public function lcs(mixed $key1, mixed $key2, array|null $options = null): mixed + public function lcs(mixed $key1, mixed $key2, ?array $options = null): mixed { return $this->initializeLazyObject()->lcs(...\func_get_args()); } @@ -297,7 +297,7 @@ public function geoadd(mixed $key, float $lng, float $lat, string $member, mixed return $this->initializeLazyObject()->geoadd(...\func_get_args()); } - public function geodist(mixed $key, string $src, string $dst, string|null $unit = null): Cluster|float|false + public function geodist(mixed $key, string $src, string $dst, ?string $unit = null): Cluster|float|false { return $this->initializeLazyObject()->geodist(...\func_get_args()); } @@ -492,7 +492,7 @@ public function unlink(mixed ...$keys): Cluster|false|int return $this->initializeLazyObject()->unlink(...\func_get_args()); } - public function expire(mixed $key, int $seconds, string|null $mode = null): Cluster|bool + public function expire(mixed $key, int $seconds, ?string $mode = null): Cluster|bool { return $this->initializeLazyObject()->expire(...\func_get_args()); } @@ -572,7 +572,7 @@ public function lpop(mixed $key, int $count = 1): mixed return $this->initializeLazyObject()->lpop(...\func_get_args()); } - public function lpos(mixed $key, mixed $value, array|null $options = null): mixed + public function lpos(mixed $key, mixed $value, ?array $options = null): mixed { return $this->initializeLazyObject()->lpos(...\func_get_args()); } @@ -707,7 +707,7 @@ public function hexists(mixed $key, mixed $member): Cluster|bool return $this->initializeLazyObject()->hexists(...\func_get_args()); } - public function hrandfield(mixed $key, array|null $options = null): Cluster|array|string|false + public function hrandfield(mixed $key, ?array $options = null): Cluster|array|string|false { return $this->initializeLazyObject()->hrandfield(...\func_get_args()); } @@ -862,7 +862,7 @@ public function getMode(bool $masked = false): int return $this->initializeLazyObject()->getMode(...\func_get_args()); } - public function scan(mixed &$iterator, array|string $key_or_address, mixed $match = null, int $count = 0, string|null $type = null): array|false + public function scan(mixed &$iterator, array|string $key_or_address, mixed $match = null, int $count = 0, ?string $type = null): array|false { return $this->initializeLazyObject()->scan($iterator, ...\array_slice(\func_get_args(), 1)); } @@ -1007,12 +1007,12 @@ public function xdel(mixed $key, array $ids): Cluster|false|int return $this->initializeLazyObject()->xdel(...\func_get_args()); } - public function xinfo(string $operation, string|null $arg1 = null, string|null $arg2 = null, int $count = -1): mixed + public function xinfo(string $operation, ?string $arg1 = null, ?string $arg2 = null, int $count = -1): mixed { return $this->initializeLazyObject()->xinfo(...\func_get_args()); } - public function xpending(mixed $key, string $group, string|null $start = null, string|null $end = null, int $count = -1, string|null $consumer = null, int $idle = 0): Cluster|array|false + public function xpending(mixed $key, string $group, ?string $start = null, ?string $end = null, int $count = -1, ?string $consumer = null, int $idle = 0): Cluster|array|false { return $this->initializeLazyObject()->xpending(...\func_get_args()); } @@ -1047,7 +1047,7 @@ public function zadd(mixed $key, mixed ...$args): mixed return $this->initializeLazyObject()->zadd(...\func_get_args()); } - public function zrandmember(mixed $key, array|null $options = null): mixed + public function zrandmember(mixed $key, ?array $options = null): mixed { return $this->initializeLazyObject()->zrandmember(...\func_get_args()); } @@ -1127,7 +1127,7 @@ public function zcount(mixed $key, mixed $min, mixed $max): Cluster|false|int return $this->initializeLazyObject()->zcount(...\func_get_args()); } - public function zdiff(array $keys, array|null $options = null): Cluster|array|false + public function zdiff(array $keys, ?array $options = null): Cluster|array|false { return $this->initializeLazyObject()->zdiff(...\func_get_args()); } @@ -1152,7 +1152,7 @@ public function zmscore(mixed $key, mixed ...$members): Cluster|array|false return $this->initializeLazyObject()->zmscore(...\func_get_args()); } - public function zinter(array $keys, array|null $weights = null, mixed $options = null): Cluster|array|false + public function zinter(array $keys, ?array $weights = null, mixed $options = null): Cluster|array|false { return $this->initializeLazyObject()->zinter(...\func_get_args()); } @@ -1162,17 +1162,17 @@ public function zintercard(array $keys, int $limit = -1): Cluster|false|int return $this->initializeLazyObject()->zintercard(...\func_get_args()); } - public function zinterstore(mixed $dstkey, array $keys, array|null $weights = null, mixed $options = null): Cluster|false|int + public function zinterstore(mixed $dstkey, array $keys, ?array $weights = null, mixed $options = null): Cluster|false|int { return $this->initializeLazyObject()->zinterstore(...\func_get_args()); } - public function zunion(array $keys, array|null $weights = null, mixed $options = null): Cluster|array|false + public function zunion(array $keys, ?array $weights = null, mixed $options = null): Cluster|array|false { return $this->initializeLazyObject()->zunion(...\func_get_args()); } - public function zunionstore(mixed $dstkey, array $keys, array|null $weights = null, mixed $options = null): Cluster|false|int + public function zunionstore(mixed $dstkey, array $keys, ?array $weights = null, mixed $options = null): Cluster|false|int { return $this->initializeLazyObject()->zunionstore(...\func_get_args()); } @@ -1197,7 +1197,7 @@ public function _masters(): array return $this->initializeLazyObject()->_masters(...\func_get_args()); } - public function copy(mixed $srckey, mixed $dstkey, array|null $options = null): Cluster|bool + public function copy(mixed $srckey, mixed $dstkey, ?array $options = null): Cluster|bool { return $this->initializeLazyObject()->copy(...\func_get_args()); } diff --git a/src/Symfony/Component/Cache/Traits/RelayProxy.php b/src/Symfony/Component/Cache/Traits/RelayProxy.php index b6d48dd543dba..43b8956771749 100644 --- a/src/Symfony/Component/Cache/Traits/RelayProxy.php +++ b/src/Symfony/Component/Cache/Traits/RelayProxy.php @@ -13,12 +13,17 @@ use Symfony\Component\Cache\Traits\Relay\BgsaveTrait; use Symfony\Component\Cache\Traits\Relay\CopyTrait; +use Symfony\Component\Cache\Traits\Relay\FtTrait; use Symfony\Component\Cache\Traits\Relay\GeosearchTrait; use Symfony\Component\Cache\Traits\Relay\GetrangeTrait; +use Symfony\Component\Cache\Traits\Relay\GetWithMetaTrait; use Symfony\Component\Cache\Traits\Relay\HsetTrait; +use Symfony\Component\Cache\Traits\Relay\IsTrackedTrait; use Symfony\Component\Cache\Traits\Relay\MoveTrait; use Symfony\Component\Cache\Traits\Relay\NullableReturnTrait; use Symfony\Component\Cache\Traits\Relay\PfcountTrait; +use Symfony\Component\Cache\Traits\Relay\Relay11Trait; +use Symfony\Component\Cache\Traits\Relay\SwapdbTrait; use Symfony\Component\VarExporter\LazyObjectInterface; use Symfony\Contracts\Service\ResetInterface; @@ -34,9 +39,12 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter { use BgsaveTrait; use CopyTrait; + use FtTrait; use GeosearchTrait; use GetrangeTrait; + use GetWithMetaTrait; use HsetTrait; + use IsTrackedTrait; use MoveTrait; use NullableReturnTrait; use PfcountTrait; @@ -44,6 +52,8 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter resetLazyObject as reset; } use RelayProxyTrait; + use Relay11Trait; + use SwapdbTrait; public function __construct($host = null, $port = 6379, $connect_timeout = 0.0, $command_timeout = 0.0, #[\SensitiveParameter] $context = [], $database = 0) { diff --git a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php index ddd6dbb291051..d7689901600ba 100644 --- a/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php +++ b/src/Symfony/Component/Config/Builder/ConfigBuilderGenerator.php @@ -126,10 +126,13 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n $class->addRequire($childClass); $this->classes[] = $childClass; + $nodeTypes = $this->getParameterTypes($node); + $paramType = $this->getParamType($nodeTypes); + $hasNormalizationClosures = $this->hasNormalizationClosures($node); $comment = $this->getComment($node); - if ($hasNormalizationClosures) { - $comment = \sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); + if ($hasNormalizationClosures && 'array' !== $paramType) { + $comment = \sprintf(" * @template TValue of %s\n * @param TValue \$value\n%s", $paramType, $comment); $comment .= \sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); $comment .= \sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); } @@ -141,8 +144,7 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n $node->getName(), $this->getType($childClass->getFqcn(), $hasNormalizationClosures) ); - $nodeTypes = $this->getParameterTypes($node); - $body = $hasNormalizationClosures ? ' + $body = $hasNormalizationClosures && 'array' !== $paramType ? ' COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static { if (!\is_array($value)) { @@ -177,7 +179,7 @@ private function handleArrayNode(ArrayNode $node, ClassBuilder $class, string $n 'COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), - 'PARAM_TYPE' => \in_array('mixed', $nodeTypes, true) ? 'mixed' : implode('|', $nodeTypes), + 'PARAM_TYPE' => $paramType, ]); $this->buildNode($node, $childClass, $this->getSubNamespace($childClass)); @@ -217,10 +219,11 @@ private function handlePrototypedArrayNode(PrototypedArrayNode $node, ClassBuild $nodeParameterTypes = $this->getParameterTypes($node); $prototypeParameterTypes = $this->getParameterTypes($prototype); + $noKey = null === $key = $node->getKeyAttribute(); if (!$prototype instanceof ArrayNode || ($prototype instanceof PrototypedArrayNode && $prototype->getPrototype() instanceof ScalarNode)) { $class->addUse(ParamConfigurator::class); $property = $class->addProperty($node->getName()); - if (null === $key = $node->getKeyAttribute()) { + if ($noKey) { // This is an array of values; don't use singular name $nodeTypesWithoutArray = array_filter($nodeParameterTypes, static fn ($type) => 'array' !== $type); $body = ' @@ -241,7 +244,7 @@ public function NAME(PARAM_TYPE $value): static 'PROPERTY' => $property->getName(), 'PROTOTYPE_TYPE' => implode('|', $prototypeParameterTypes), 'EXTRA_TYPE' => $nodeTypesWithoutArray ? '|'.implode('|', $nodeTypesWithoutArray) : '', - 'PARAM_TYPE' => \in_array('mixed', $nodeParameterTypes, true) ? 'mixed' : 'ParamConfigurator|'.implode('|', $nodeParameterTypes), + 'PARAM_TYPE' => $this->getParamType($nodeParameterTypes, true), ]); } else { $body = ' @@ -258,7 +261,7 @@ public function NAME(string $VAR, TYPE $VALUE): static $class->addMethod($methodName, $body, [ 'PROPERTY' => $property->getName(), - 'TYPE' => \in_array('mixed', $prototypeParameterTypes, true) ? 'mixed' : 'ParamConfigurator|'.implode('|', $prototypeParameterTypes), + 'TYPE' => $this->getParamType($prototypeParameterTypes, true), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value', ]); @@ -279,9 +282,11 @@ public function NAME(string $VAR, TYPE $VALUE): static $this->getType($childClass->getFqcn().'[]', $hasNormalizationClosures) ); + $paramType = $this->getParamType($noKey ? $nodeParameterTypes : $prototypeParameterTypes); + $comment = $this->getComment($node); - if ($hasNormalizationClosures) { - $comment = \sprintf(" * @template TValue\n * @param TValue \$value\n%s", $comment); + if ($hasNormalizationClosures && 'array' !== $paramType) { + $comment = \sprintf(" * @template TValue of %s\n * @param TValue \$value\n%s", $paramType, $comment); $comment .= \sprintf(' * @return %s|$this'."\n", $childClass->getFqcn()); $comment .= \sprintf(' * @psalm-return (TValue is array ? %s : static)'."\n ", $childClass->getFqcn()); } @@ -289,8 +294,8 @@ public function NAME(string $VAR, TYPE $VALUE): static $comment = "/**\n$comment*/\n"; } - if (null === $key = $node->getKeyAttribute()) { - $body = $hasNormalizationClosures ? ' + if ($noKey) { + $body = $hasNormalizationClosures && 'array' !== $paramType ? ' COMMENTpublic function NAME(PARAM_TYPE $value = []): CLASS|static { $this->_usedProperties[\'PROPERTY\'] = true; @@ -312,10 +317,10 @@ public function NAME(string $VAR, TYPE $VALUE): static 'COMMENT' => $comment, 'PROPERTY' => $property->getName(), 'CLASS' => $childClass->getFqcn(), - 'PARAM_TYPE' => \in_array('mixed', $nodeParameterTypes, true) ? 'mixed' : implode('|', $nodeParameterTypes), + 'PARAM_TYPE' => $paramType, ]); } else { - $body = $hasNormalizationClosures ? ' + $body = $hasNormalizationClosures && 'array' !== $paramType ? ' COMMENTpublic function NAME(string $VAR, PARAM_TYPE $VALUE = []): CLASS|static { if (!\is_array($VALUE)) { @@ -351,7 +356,7 @@ public function NAME(string $VAR, TYPE $VALUE): static 'CLASS' => $childClass->getFqcn(), 'VAR' => '' === $key ? 'key' : $key, 'VALUE' => 'value' === $key ? 'data' : 'value', - 'PARAM_TYPE' => \in_array('mixed', $prototypeParameterTypes, true) ? 'mixed' : implode('|', $prototypeParameterTypes), + 'PARAM_TYPE' => $paramType, ]); } @@ -596,4 +601,9 @@ private function getType(string $classType, bool $hasNormalizationClosures): str { return $classType.($hasNormalizationClosures ? '|scalar' : ''); } + + private function getParamType(array $types, bool $withParamConfigurator = false): string + { + return \in_array('mixed', $types, true) ? 'mixed' : ($withParamConfigurator ? 'ParamConfigurator|' : '').implode('|', $types); + } } diff --git a/src/Symfony/Component/Config/FileLocatorInterface.php b/src/Symfony/Component/Config/FileLocatorInterface.php index 87cecf47729bb..24bc70964a510 100644 --- a/src/Symfony/Component/Config/FileLocatorInterface.php +++ b/src/Symfony/Component/Config/FileLocatorInterface.php @@ -27,10 +27,10 @@ interface FileLocatorInterface * * @return string|string[] The full path to the file or an array of file paths * + * @psalm-return ($first is true ? string : string[]) + * * @throws \InvalidArgumentException If $name is empty * @throws FileLocatorFileNotFoundException If a file is not found - * - * @psalm-return ($first is true ? string : string[]) */ public function locate(string $name, ?string $currentPath = null, bool $first = true): string|array; } diff --git a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php index e039329ca9770..5bf026639c8bf 100644 --- a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php +++ b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php @@ -122,7 +122,7 @@ private function generateSignature(\ReflectionClass $class): iterable yield print_r($attributes, true); $attributes = []; - yield $class->getDocComment(); + yield $class->getDocComment() ?: ''; yield (int) $class->isFinal(); yield (int) $class->isAbstract(); @@ -134,6 +134,14 @@ private function generateSignature(\ReflectionClass $class): iterable yield print_r($class->getConstants(), true); } + foreach ($class->getReflectionConstants() as $constant) { + foreach ($constant->getAttributes() as $a) { + $attributes[] = [$a->getName(), (string) $a]; + } + yield $constant->name.print_r($attributes, true); + $attributes = []; + } + if (!$class->isInterface()) { $defaults = $class->getDefaultProperties(); @@ -144,7 +152,7 @@ private function generateSignature(\ReflectionClass $class): iterable yield print_r($attributes, true); $attributes = []; - yield $p->getDocComment(); + yield $p->getDocComment() ?: ''; yield $p->isDefault() ? '' : ''; yield $p->isPublic() ? 'public' : 'protected'; yield $p->isStatic() ? 'static' : ''; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.config.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.config.php new file mode 100644 index 0000000000000..642345ca5dd63 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.config.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Config\ArrayValuesConfig; + +return static function (ArrayValuesConfig $config) { + $config->transports('foo')->dsn('bar'); + $config->transports('bar', ['dsn' => 'foobar']); + + $config->errorPages()->withTrace(false); +}; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.output.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.output.php new file mode 100644 index 0000000000000..ab56d53a2f562 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.output.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + 'transports' => [ + 'foo' => [ + 'dsn' => 'bar', + ], + 'bar' => [ + 'dsn' => 'foobar', + ], + ], + 'error_pages' => [ + 'with_trace' => false, + ] +]; diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.php new file mode 100644 index 0000000000000..457e78a1f7118 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues.php @@ -0,0 +1,42 @@ +getRootNode(); + $rootNode + ->children() + ->arrayNode('transports') + ->normalizeKeys(false) + ->useAttributeAsKey('name') + ->arrayPrototype() + ->beforeNormalization() + ->ifString() + ->then(function (string $dsn) { + return ['dsn' => $dsn]; + }) + ->end() + ->fixXmlConfig('option') + ->children() + ->scalarNode('dsn')->end() + ->end() + ->end() + ->end() + ->arrayNode('error_pages') + ->canBeEnabled() + ->children() + ->booleanNode('with_trace')->end() + ->end() + ->end() + ->end(); + + return $tb; + } +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/ErrorPagesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/ErrorPagesConfig.php new file mode 100644 index 0000000000000..36ccb016dc6d9 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/ErrorPagesConfig.php @@ -0,0 +1,75 @@ +_usedProperties['enabled'] = true; + $this->enabled = $value; + + return $this; + } + + /** + * @default null + * @param ParamConfigurator|bool $value + * @return $this + */ + public function withTrace($value): static + { + $this->_usedProperties['withTrace'] = true; + $this->withTrace = $value; + + return $this; + } + + public function __construct(array $value = []) + { + if (array_key_exists('enabled', $value)) { + $this->_usedProperties['enabled'] = true; + $this->enabled = $value['enabled']; + unset($value['enabled']); + } + + if (array_key_exists('with_trace', $value)) { + $this->_usedProperties['withTrace'] = true; + $this->withTrace = $value['with_trace']; + unset($value['with_trace']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (isset($this->_usedProperties['enabled'])) { + $output['enabled'] = $this->enabled; + } + if (isset($this->_usedProperties['withTrace'])) { + $output['with_trace'] = $this->withTrace; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/TransportsConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/TransportsConfig.php new file mode 100644 index 0000000000000..c1ad5437834f8 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValues/TransportsConfig.php @@ -0,0 +1,52 @@ +_usedProperties['dsn'] = true; + $this->dsn = $value; + + return $this; + } + + public function __construct(array $value = []) + { + if (array_key_exists('dsn', $value)) { + $this->_usedProperties['dsn'] = true; + $this->dsn = $value['dsn']; + unset($value['dsn']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (isset($this->_usedProperties['dsn'])) { + $output['dsn'] = $this->dsn; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValuesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValuesConfig.php new file mode 100644 index 0000000000000..818a14fcbcd9b --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ArrayValues/Symfony/Config/ArrayValuesConfig.php @@ -0,0 +1,96 @@ +_usedProperties['transports'] = true; + $this->transports[$name] = $value; + + return $this; + } + + if (!isset($this->transports[$name]) || !$this->transports[$name] instanceof \Symfony\Config\ArrayValues\TransportsConfig) { + $this->_usedProperties['transports'] = true; + $this->transports[$name] = new \Symfony\Config\ArrayValues\TransportsConfig($value); + } elseif (1 < \func_num_args()) { + throw new InvalidConfigurationException('The node created by "transports()" has already been initialized. You cannot pass values the second time you call transports().'); + } + + return $this->transports[$name]; + } + + /** + * @default {"enabled":false} + */ + public function errorPages(array $value = []): \Symfony\Config\ArrayValues\ErrorPagesConfig + { + if (null === $this->errorPages) { + $this->_usedProperties['errorPages'] = true; + $this->errorPages = new \Symfony\Config\ArrayValues\ErrorPagesConfig($value); + } elseif (0 < \func_num_args()) { + throw new InvalidConfigurationException('The node created by "errorPages()" has already been initialized. You cannot pass values the second time you call errorPages().'); + } + + return $this->errorPages; + } + + public function getExtensionAlias(): string + { + return 'array_values'; + } + + public function __construct(array $value = []) + { + if (array_key_exists('transports', $value)) { + $this->_usedProperties['transports'] = true; + $this->transports = array_map(fn ($v) => \is_array($v) ? new \Symfony\Config\ArrayValues\TransportsConfig($v) : $v, $value['transports']); + unset($value['transports']); + } + + if (array_key_exists('error_pages', $value)) { + $this->_usedProperties['errorPages'] = true; + $this->errorPages = \is_array($value['error_pages']) ? new \Symfony\Config\ArrayValues\ErrorPagesConfig($value['error_pages']) : $value['error_pages']; + unset($value['error_pages']); + } + + if ([] !== $value) { + throw new InvalidConfigurationException(sprintf('The following keys are not supported by "%s": ', __CLASS__).implode(', ', array_keys($value))); + } + } + + public function toArray(): array + { + $output = []; + if (isset($this->_usedProperties['transports'])) { + $output['transports'] = array_map(fn ($v) => $v instanceof \Symfony\Config\ArrayValues\TransportsConfig ? $v->toArray() : $v, $this->transports); + } + if (isset($this->_usedProperties['errorPages'])) { + $output['error_pages'] = $this->errorPages instanceof \Symfony\Config\ArrayValues\ErrorPagesConfig ? $this->errorPages->toArray() : $this->errorPages; + } + + return $output; + } + +} diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypes/NestedConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypes/NestedConfig.php index 2cc1fb3275e78..2b3f19e87fb6f 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypes/NestedConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypes/NestedConfig.php @@ -17,7 +17,7 @@ class NestedConfig private $_usedProperties = []; /** - * @template TValue + * @template TValue of mixed * @param TValue $value * @default {"enabled":null} * @return \Symfony\Config\ScalarNormalizedTypes\Nested\NestedObjectConfig|$this @@ -43,7 +43,7 @@ public function nestedObject(mixed $value = []): \Symfony\Config\ScalarNormalize } /** - * @template TValue + * @template TValue of mixed * @param TValue $value * @return \Symfony\Config\ScalarNormalizedTypes\Nested\NestedListObjectConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\ScalarNormalizedTypes\Nested\NestedListObjectConfig : static) diff --git a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php index 1794ede72e18c..66107b8f19730 100644 --- a/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php +++ b/src/Symfony/Component/Config/Tests/Builder/Fixtures/ScalarNormalizedTypes/Symfony/Config/ScalarNormalizedTypesConfig.php @@ -48,7 +48,7 @@ public function keyedArray(string $name, ParamConfigurator|string|array $value): } /** - * @template TValue + * @template TValue of mixed * @param TValue $value * @default {"enabled":null} * @return \Symfony\Config\ScalarNormalizedTypes\ObjectConfig|$this @@ -74,7 +74,7 @@ public function object(mixed $value = []): \Symfony\Config\ScalarNormalizedTypes } /** - * @template TValue + * @template TValue of mixed * @param TValue $value * @return \Symfony\Config\ScalarNormalizedTypes\ListObjectConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\ScalarNormalizedTypes\ListObjectConfig : static) @@ -92,7 +92,7 @@ public function listObject(mixed $value = []): \Symfony\Config\ScalarNormalizedT } /** - * @template TValue + * @template TValue of mixed * @param TValue $value * @return \Symfony\Config\ScalarNormalizedTypes\KeyedListObjectConfig|$this * @psalm-return (TValue is array ? \Symfony\Config\ScalarNormalizedTypes\KeyedListObjectConfig : static) diff --git a/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php b/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php index 680010f00fc3c..856bcf279575e 100644 --- a/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php +++ b/src/Symfony/Component/Config/Tests/Builder/GeneratedConfigTest.php @@ -58,6 +58,7 @@ public static function fixtureNames() 'AddToList' => 'add_to_list', 'NodeInitialValues' => 'node_initial_values', 'ArrayExtraKeys' => 'array_extra_keys', + 'ArrayValues' => 'array_values', ]; foreach ($array as $name => $alias) { @@ -159,10 +160,12 @@ public function testSetExtraKeyMethodIsNotGeneratedWhenAllowExtraKeysIsFalse() */ private function generateConfigBuilder(string $configurationClass, ?string &$outputDir = null) { - $outputDir = tempnam(sys_get_temp_dir(), 'sf_config_builder_'); - unlink($outputDir); - mkdir($outputDir); - $this->tempDir[] = $outputDir; + if (null === $outputDir) { + $outputDir = tempnam(sys_get_temp_dir(), 'sf_config_builder_'); + unlink($outputDir); + mkdir($outputDir); + $this->tempDir[] = $outputDir; + } $configuration = new $configurationClass(); $rootNode = $configuration->getConfigTreeBuilder()->buildTree(); @@ -193,6 +196,8 @@ private function assertDirectorySame($expected, $current) } $currentFiles[substr($file->getPathname(), \strlen($current))] = $file->getPathname(); } + ksort($expectedFiles); + ksort($currentFiles); $this->assertSame(array_keys($expectedFiles), array_keys($currentFiles)); foreach ($expectedFiles as $fileName => $filePath) { diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index e7e36a0635933..26c5088636aaa 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -195,6 +195,30 @@ public function testIgnoresObjectsInSignature() TestServiceWithStaticProperty::$initializedObject = new TestServiceWithStaticProperty(); $this->assertTrue($res->isFresh(0)); } + + public function testEnum() + { + $res = new ReflectionClassResource($enum = new \ReflectionClass(SomeEnum::class)); + $r = new \ReflectionClass(ReflectionClassResource::class); + $generateSignature = $r->getMethod('generateSignature')->getClosure($res); + $actual = implode("\n", iterator_to_array($generateSignature($enum))); + $this->assertStringContainsString('UnitEnum', $actual); + $this->assertStringContainsString('TestAttribute', $actual); + $this->assertStringContainsString('Beta', $actual); + } + + public function testBackedEnum() + { + $res = new ReflectionClassResource($enum = new \ReflectionClass(SomeBackedEnum::class)); + $r = new \ReflectionClass(ReflectionClassResource::class); + $generateSignature = $r->getMethod('generateSignature')->getClosure($res); + $actual = implode("\n", iterator_to_array($generateSignature($enum))); + $this->assertStringContainsString('UnitEnum', $actual); + $this->assertStringContainsString('BackedEnum', $actual); + $this->assertStringContainsString('TestAttribute', $actual); + $this->assertStringContainsString('Beta', $actual); + $this->assertStringContainsString('beta', $actual); + } } interface DummyInterface @@ -225,3 +249,19 @@ class TestServiceWithStaticProperty { public static object $initializedObject; } + +enum SomeEnum +{ + case Alpha; + + #[TestAttribute] + case Beta; +} + +enum SomeBackedEnum: string +{ + case Alpha = 'alpha'; + + #[TestAttribute] + case Beta = 'beta'; +} diff --git a/src/Symfony/Component/Console/Attribute/Option.php b/src/Symfony/Component/Console/Attribute/Option.php index 2f0256b177658..788353463a2ca 100644 --- a/src/Symfony/Component/Console/Attribute/Option.php +++ b/src/Symfony/Component/Console/Attribute/Option.php @@ -158,7 +158,7 @@ public function resolveValue(InputInterface $input): mixed private function handleUnion(\ReflectionUnionType $type): self { $types = array_map( - static fn(\ReflectionType $t) => $t instanceof \ReflectionNamedType ? $t->getName() : null, + static fn (\ReflectionType $t) => $t instanceof \ReflectionNamedType ? $t->getName() : null, $type->getTypes(), ); diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index f6cd8499791f1..72a10cf7603c4 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -134,7 +134,7 @@ public function __construct(?string $name = null) $this->setHelp($attribute?->help ?? ''); } - if (\is_callable($this) && (new \ReflectionMethod($this, 'execute'))->getDeclaringClass()->name === self::class) { + if (\is_callable($this) && self::class === (new \ReflectionMethod($this, 'execute'))->getDeclaringClass()->name) { $this->code = new InvokableCommand($this, $this(...)); } diff --git a/src/Symfony/Component/Console/Command/TraceableCommand.php b/src/Symfony/Component/Console/Command/TraceableCommand.php index 315f385de9aa2..ed11cc29f872b 100644 --- a/src/Symfony/Component/Console/Command/TraceableCommand.php +++ b/src/Symfony/Component/Console/Command/TraceableCommand.php @@ -292,7 +292,7 @@ public function run(InputInterface $input, OutputInterface $output): int $event = $this->stopwatch->start($this->getName(), 'command'); try { - $this->exitCode = parent::run($input, $output); + $this->exitCode = $this->command->run($input, $output); } finally { $event->stop(); diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php index 956303709645f..9a8e696cd4135 100644 --- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php @@ -108,7 +108,7 @@ private function getInputOptionData(InputOption $option, bool $negated = false): 'is_value_required' => false, 'is_multiple' => false, 'description' => 'Negate the "--'.$option->getName().'" option', - 'default' => false, + 'default' => null === $option->getDefault() ? null : !$option->getDefault(), ] : [ 'name' => '--'.$option->getName(), 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 3c8c287e8375f..eab86976d9e76 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Formatter; use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Helper\Helper; use function Symfony\Component\String\b; @@ -136,9 +137,11 @@ public function formatAndWrap(?string $message, int $width): string continue; } + // convert byte position to character position. + $pos = Helper::length(substr($message, 0, $pos)); // add the text up to the next tag - $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); - $offset = $pos + \strlen($text); + $output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $offset = $pos + Helper::length($text); // opening tag? if ($open = '/' !== $text[1]) { @@ -159,7 +162,7 @@ public function formatAndWrap(?string $message, int $width): string } } - $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength); + $output .= $this->applyCurrentStyle(Helper::substr($message, $offset), $output, $width, $currentLineLength); return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); } @@ -226,8 +229,18 @@ private function applyCurrentStyle(string $text, string $current, int $width, in } if ($currentLineLength) { - $prefix = substr($text, 0, $i = $width - $currentLineLength)."\n"; - $text = substr($text, $i); + $lines = explode("\n", $text, 2); + $prefix = Helper::substr($lines[0], 0, $i = $width - $currentLineLength)."\n"; + $text = Helper::substr($lines[0], $i); + + if (isset($lines[1])) { + // $prefix may contain the full first line in which the \n is already a part of $prefix. + if ('' !== $text) { + $text .= "\n"; + } + + $text .= $lines[1]; + } } else { $prefix = ''; } @@ -242,8 +255,8 @@ private function applyCurrentStyle(string $text, string $current, int $width, in $lines = explode("\n", $text); - foreach ($lines as $line) { - $currentLineLength += \strlen($line); + foreach ($lines as $i => $line) { + $currentLineLength = 0 === $i ? $currentLineLength + Helper::length($line) : Helper::length($line); if ($width <= $currentLineLength) { $currentLineLength = 0; } diff --git a/src/Symfony/Component/Console/Helper/Helper.php b/src/Symfony/Component/Console/Helper/Helper.php index bdd8d9e956787..46e7e2f58308d 100644 --- a/src/Symfony/Component/Console/Helper/Helper.php +++ b/src/Symfony/Component/Console/Helper/Helper.php @@ -80,6 +80,10 @@ public static function substr(?string $string, int $from, ?int $length = null): { $string ??= ''; + if (preg_match('//u', $string)) { + return (new UnicodeString($string))->slice($from, $length); + } + if (false === $encoding = mb_detect_encoding($string, null, true)) { return substr($string, $from, $length); } diff --git a/src/Symfony/Component/Console/Helper/TreeNode.php b/src/Symfony/Component/Console/Helper/TreeNode.php index 7f2ed8a4af371..8c35266c12a2a 100644 --- a/src/Symfony/Component/Console/Helper/TreeNode.php +++ b/src/Symfony/Component/Console/Helper/TreeNode.php @@ -58,7 +58,7 @@ public function getValue(): string public function addChild(self|string|callable $node): self { if (\is_string($node)) { - $node = new self($node, $this); + $node = new self($node); } $this->children[] = $node; diff --git a/src/Symfony/Component/Console/Messenger/RunCommandMessageHandler.php b/src/Symfony/Component/Console/Messenger/RunCommandMessageHandler.php index 0fdf7d01724ac..df5f48af09b92 100644 --- a/src/Symfony/Component/Console/Messenger/RunCommandMessageHandler.php +++ b/src/Symfony/Component/Console/Messenger/RunCommandMessageHandler.php @@ -16,6 +16,8 @@ use Symfony\Component\Console\Exception\RunCommandFailedException; use Symfony\Component\Console\Input\StringInput; use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Messenger\Exception\RecoverableExceptionInterface; +use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface; /** * @author Kevin Bond @@ -36,6 +38,8 @@ public function __invoke(RunCommandMessage $message): RunCommandContext try { $exitCode = $this->application->run($input, $output); + } catch (UnrecoverableExceptionInterface|RecoverableExceptionInterface $e) { + throw $e; } catch (\Throwable $e) { throw new RunCommandFailedException($e, new RunCommandContext($message, Command::FAILURE, $output->fetch())); } diff --git a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php index 5ab7951e7f575..9fc40809a3d2f 100644 --- a/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/InvokableCommandTest.php @@ -156,6 +156,7 @@ public function testExecuteHasPriorityOverInvokeMethod() { $command = new class extends Command { public string $called; + protected function execute(InputInterface $input, OutputInterface $output): int { $this->called = __FUNCTION__; @@ -179,6 +180,7 @@ public function testCallInvokeMethodWhenExtendingCommandClass() { $command = new class extends Command { public string $called; + public function __invoke(): int { $this->called = __FUNCTION__; @@ -195,7 +197,9 @@ public function testInvalidReturnType() { $command = new Command('foo'); $command->setCode(new class { - public function __invoke() {} + public function __invoke() + { + } }); $this->expectException(\TypeError::class); @@ -333,16 +337,16 @@ public function testInvalidOptionDefinition(callable $code) public static function provideInvalidOptionDefinitions(): \Generator { yield 'no-default' => [ - function (#[Option] string $a) {} + function (#[Option] string $a) {}, ]; yield 'nullable-bool-default-true' => [ - function (#[Option] ?bool $a = true) {} + function (#[Option] ?bool $a = true) {}, ]; yield 'nullable-bool-default-false' => [ - function (#[Option] ?bool $a = false) {} + function (#[Option] ?bool $a = false) {}, ]; yield 'invalid-union-type' => [ - function (#[Option] array|bool $a = false) {} + function (#[Option] array|bool $a = false) {}, ]; yield 'union-type-cannot-allow-null' => [ function (#[Option] string|bool|null $a = null) {}, diff --git a/src/Symfony/Component/Console/Tests/Command/TraceableCommandTest.php b/src/Symfony/Component/Console/Tests/Command/TraceableCommandTest.php new file mode 100644 index 0000000000000..1bf709f8bce0e --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Command/TraceableCommandTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\TraceableCommand; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Console\Tests\Fixtures\LoopExampleCommand; +use Symfony\Component\Stopwatch\Stopwatch; + +class TraceableCommandTest extends TestCase +{ + private Application $application; + + protected function setUp(): void + { + $this->application = new Application(); + $this->application->add(new LoopExampleCommand()); + } + + public function testRunIsOverriddenWithoutProfile() + { + $command = $this->application->find('app:loop:example'); + $commandTester = new CommandTester($command); + $commandTester->execute([]); + $commandTester->assertCommandIsSuccessful(); + + $output = $commandTester->getDisplay(); + $this->assertLoopOutputCorrectness($output); + } + + public function testRunIsNotOverriddenWithProfile() + { + // Simulate the bug environment by wrapping + // our command in TraceableCommand, which is what Symfony does + // when you use the --profile option. + $command = new LoopExampleCommand(); + $traceableCommand = new TraceableCommand($command, new Stopwatch()); + + $this->application->add($traceableCommand); + + $commandTester = new CommandTester($traceableCommand); + $commandTester->execute([]); + $commandTester->assertCommandIsSuccessful(); + + $output = $commandTester->getDisplay(); + $this->assertLoopOutputCorrectness($output); + } + + public function assertLoopOutputCorrectness(string $output) + { + $completeChar = '\\' !== \DIRECTORY_SEPARATOR ? '▓' : '='; + self::assertMatchesRegularExpression('~3/3\s+\['.$completeChar.'+]\s+100%~u', $output); + self::assertStringContainsString('Loop finished.', $output); + self::assertEquals(3, substr_count($output, 'Hello world')); + } +} diff --git a/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php b/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php index 399bd8f2368db..914ed35970c7c 100644 --- a/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php +++ b/src/Symfony/Component/Console/Tests/Descriptor/JsonDescriptorTest.php @@ -36,10 +36,9 @@ private function normalizeOutputRecursively($output) return array_map($this->normalizeOutputRecursively(...), $output); } - if (null === $output) { - return null; - } - - return parent::normalizeOutput($output); + return match ($output) { + null, true, false => $output, + default => parent::normalizeOutput($output), + }; } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/AbstractLoopCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/AbstractLoopCommand.php new file mode 100644 index 0000000000000..c3715067ebcb3 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/AbstractLoopCommand.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +abstract class AbstractLoopCommand extends Command +{ + public function run(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $contexts = [1, 2, 3]; + $io->progressStart(count($contexts)); + $code = self::SUCCESS; + + foreach ($contexts as $ignored) { + $io->progressAdvance(); + try { + parent::run($input, $output); + } catch (\Throwable) { + $code = self::FAILURE; + } + } + $io->progressFinish(); + $output->writeln("\nLoop finished."); + + return $code; + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/LoopExampleCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/LoopExampleCommand.php new file mode 100644 index 0000000000000..d9eeb4db97f67 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/LoopExampleCommand.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Fixtures; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +#[AsCommand('app:loop:example')] +class LoopExampleCommand extends AbstractLoopCommand +{ + protected function execute(InputInterface $input, OutputInterface $output): int + { + $output->writeln(' Hello world'); + + return Command::SUCCESS; + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json index 4a6f411f55c48..c0e66444e9b15 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_2.json +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_2.json @@ -94,7 +94,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null }, "shell": { "name": "--shell", @@ -224,7 +224,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null }, "debug": { "name": "--debug", @@ -345,7 +345,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null } } } @@ -457,7 +457,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null }, "short": { "name": "--short", @@ -554,7 +554,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null } } } @@ -659,7 +659,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null } } } @@ -745,7 +745,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null } } } @@ -833,7 +833,7 @@ "is_value_required": false, "is_multiple": false, "description": "Do not ask any interactive question", - "default": false + "default": null } } } diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 477f1bdf6bd70..b66b6abe487a2 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -177,7 +177,7 @@ public function testInlineStyleOptions(string $tag, ?string $expected = null, ?s $expected = $tag.$input.''; $this->assertSame($expected, $formatter->format($expected)); } else { - /* @var OutputFormatterStyle $result */ + /** @var OutputFormatterStyle $result */ $this->assertInstanceOf(OutputFormatterStyle::class, $result); $this->assertSame($expected, $formatter->format($tag.$input.'')); $this->assertSame($expected, $formatter->format($tag.$input.'')); @@ -365,6 +365,14 @@ public function testFormatAndWrap() $this->assertSame("Lore\nm \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m \ndolo\nr \e[32msi\e[39m\n\e[32mt\e[39m am\net", $formatter->formatAndWrap('Lorem ipsum dolor sit amet', 4)); $this->assertSame("Lorem \e[37;41mip\e[39;49m\n\e[37;41msum\e[39;49m dolo\nr \e[32msit\e[39m am\net", $formatter->formatAndWrap('Lorem ipsum dolor sit amet', 8)); $this->assertSame("Lorem \e[37;41mipsum\e[39;49m dolor \e[32m\e[39m\n\e[32msit\e[39m, \e[37;41mamet\e[39;49m et \e[32mlauda\e[39m\n\e[32mntium\e[39m architecto", $formatter->formatAndWrap('Lorem ipsum dolor sit, amet et laudantium architecto', 18)); + $this->assertSame("\e[37;41mnon-empty-array\e[39;49m\e[37;41m\e[39;49m given.\n🪪 argument.type", $formatter->formatAndWrap("non-empty-array given.\n🪪 argument.type", 38)); + $this->assertSame("Usuário {{user_name}} não é válid\no.", $formatter->formatAndWrap('Usuário {{user_name}} não é válido.', 50)); + $this->assertSame("foo\e[37;41mb\e[39;49m\n\e[37;41mar\e[39;49mbaz", $formatter->formatAndWrap("foob\narbaz", 7)); + $this->assertSame("foo\e[37;41mbar\e[39;49mbaz\nnewline", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobarbaz\n\e[37;41mnewline\e[39;49m", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobar\e[37;41mbaz\e[39;49m\n\e[37;41mnewline\e[39;49m", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobar\e[37;41mbazne\e[39;49m\n\e[37;41mwline\e[39;49m", $formatter->formatAndWrap("foobarbazne\nwline", 11)); + $this->assertSame("foobar\e[37;41mbazne\e[39;49m\n\e[37;41mw\e[39;49m\n\e[37;41mline\e[39;49m", $formatter->formatAndWrap("foobarbaznew\nline", 11)); $formatter = new OutputFormatter(); @@ -376,6 +384,14 @@ public function testFormatAndWrap() $this->assertSame(" rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\nlínès", $formatter->formatAndWrap(' rèälly löng tîtlè thät cöüld nèêd múltîplê línès', 10)); $this->assertSame(" rèälly\nlöng tîtlè\nthät cöüld\nnèêd\nmúltîplê\n línès", $formatter->formatAndWrap(" rèälly löng tîtlè thät cöüld nèêd múltîplê\n línès", 10)); $this->assertSame('', $formatter->formatAndWrap(null, 5)); + $this->assertSame("non-empty-array given.\n🪪 argument.type", $formatter->formatAndWrap("non-empty-array given.\n🪪 argument.type", 38)); + $this->assertSame("Usuário {{user_name}} não é válid\no.", $formatter->formatAndWrap('Usuário {{user_name}} não é válido.', 50)); + $this->assertSame("foob\narbaz", $formatter->formatAndWrap("foob\narbaz", 7)); + $this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobarbaz\nnewline", $formatter->formatAndWrap("foobarbaz\nnewline", 11)); + $this->assertSame("foobarbazne\nwline", $formatter->formatAndWrap("foobarbazne\nwline", 11)); + $this->assertSame("foobarbazne\nw\nline", $formatter->formatAndWrap("foobarbaznew\nline", 11)); } } diff --git a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php index ba74035f5cdfe..c0278cc330462 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php @@ -423,7 +423,7 @@ public function testOverwriteWithSectionOutputAndEol() $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); $bar = new ProgressBar($output, 50, 0); - $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%' . PHP_EOL); + $bar->setFormat('[%bar%] %percent:3s%%'.\PHP_EOL.'%message%'.\PHP_EOL); $bar->setMessage(''); $bar->start(); $bar->display(); @@ -435,8 +435,8 @@ public function testOverwriteWithSectionOutputAndEol() rewind($output->getStream()); $this->assertEquals(escapeshellcmd( '[>---------------------------] 0%'.\PHP_EOL.\PHP_EOL. - "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL. 'Doing something...' . \PHP_EOL . - "\x1b[2A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. 'Doing something foo...' . \PHP_EOL), + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL.'Doing something...'.\PHP_EOL. + "\x1b[2A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL.'Doing something foo...'.\PHP_EOL), escapeshellcmd(stream_get_contents($output->getStream())) ); } @@ -448,7 +448,7 @@ public function testOverwriteWithSectionOutputAndEolWithEmptyMessage() $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); $bar = new ProgressBar($output, 50, 0); - $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%'); + $bar->setFormat('[%bar%] %percent:3s%%'.\PHP_EOL.'%message%'); $bar->setMessage('Start'); $bar->start(); $bar->display(); @@ -460,8 +460,8 @@ public function testOverwriteWithSectionOutputAndEolWithEmptyMessage() rewind($output->getStream()); $this->assertEquals(escapeshellcmd( '[>---------------------------] 0%'.\PHP_EOL.'Start'.\PHP_EOL. - "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL . - "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. 'Doing something...' . \PHP_EOL), + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL. + "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL.'Doing something...'.\PHP_EOL), escapeshellcmd(stream_get_contents($output->getStream())) ); } @@ -473,7 +473,7 @@ public function testOverwriteWithSectionOutputAndEolWithEmptyMessageComment() $output = new ConsoleSectionOutput($stream->getStream(), $sections, $stream->getVerbosity(), $stream->isDecorated(), new OutputFormatter()); $bar = new ProgressBar($output, 50, 0); - $bar->setFormat('[%bar%] %percent:3s%%' . PHP_EOL . '%message%'); + $bar->setFormat('[%bar%] %percent:3s%%'.\PHP_EOL.'%message%'); $bar->setMessage('Start'); $bar->start(); $bar->display(); @@ -485,8 +485,8 @@ public function testOverwriteWithSectionOutputAndEolWithEmptyMessageComment() rewind($output->getStream()); $this->assertEquals(escapeshellcmd( '[>---------------------------] 0%'.\PHP_EOL."\x1b[33mStart\x1b[39m".\PHP_EOL. - "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL . - "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL. "\x1b[33mDoing something...\x1b[39m" . \PHP_EOL), + "\x1b[2A\x1b[0J".'[>---------------------------] 2%'.\PHP_EOL. + "\x1b[1A\x1b[0J".'[=>--------------------------] 4%'.\PHP_EOL."\x1b[33mDoing something...\x1b[39m".\PHP_EOL), escapeshellcmd(stream_get_contents($output->getStream())) ); } diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 52ae233011a3a..eb85364dae5fb 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -2099,12 +2099,12 @@ public function testGithubIssue60038WidthOfCellWithEmoji() ->setHeaderTitle('Test Title') ->setHeaders(['Title', 'Author']) ->setRows([ - ["🎭 💫 ☯"." Divine Comedy", "Dante Alighieri"], + ['🎭 💫 ☯ Divine Comedy', 'Dante Alighieri'], // the snowflake (e2 9d 84 ef b8 8f) has a variant selector - ["👑 ❄️ 🗡"." Game of Thrones", "George R.R. Martin"], + ['👑 ❄️ 🗡 Game of Thrones', 'George R.R. Martin'], // the snowflake in text style (e2 9d 84 ef b8 8e) has a variant selector - ["❄︎❄︎❄︎ snowflake in text style ❄︎❄︎❄︎", ""], - ["And a very long line to show difference in previous lines", ""], + ['❄︎❄︎❄︎ snowflake in text style ❄︎❄︎❄︎', ''], + ['And a very long line to show difference in previous lines', ''], ]) ; $table->render(); diff --git a/src/Symfony/Component/Console/Tests/Helper/TreeHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/TreeHelperTest.php index 15ec0f0b23707..5d1399b27aef7 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TreeHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TreeHelperTest.php @@ -195,6 +195,26 @@ public function testRenderNodeWithMultipleChildren() TREE, self::normalizeLineBreaks(trim($output->fetch()))); } + public function testRenderNodeWithMultipleChildrenWithStringConversion() + { + $rootNode = new TreeNode('Root'); + + $rootNode->addChild('Child 1'); + $rootNode->addChild('Child 2'); + $rootNode->addChild('Child 3'); + + $output = new BufferedOutput(); + $tree = TreeHelper::createTree($output, $rootNode); + + $tree->render(); + $this->assertSame(<<fetch()))); + } + public function testRenderTreeWithDuplicateNodeNames() { $rootNode = new TreeNode('Root'); diff --git a/src/Symfony/Component/Console/Tests/Helper/TreeNodeTest.php b/src/Symfony/Component/Console/Tests/Helper/TreeNodeTest.php index 981e7ea477bfb..0e80da3bd069c 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TreeNodeTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TreeNodeTest.php @@ -34,6 +34,24 @@ public function testAddingChildren() $this->assertSame($child, iterator_to_array($root->getChildren())[0]); } + public function testAddingChildrenAsString() + { + $root = new TreeNode('Root'); + + $root->addChild('Child 1'); + $root->addChild('Child 2'); + + $this->assertSame(2, iterator_count($root->getChildren())); + + $children = iterator_to_array($root->getChildren()); + + $this->assertSame(0, iterator_count($children[0]->getChildren())); + $this->assertSame(0, iterator_count($children[1]->getChildren())); + + $this->assertSame('Child 1', $children[0]->getValue()); + $this->assertSame('Child 2', $children[1]->getValue()); + } + public function testAddingChildrenWithGenerators() { $root = new TreeNode('Root'); diff --git a/src/Symfony/Component/Console/Tests/Messenger/RunCommandMessageHandlerTest.php b/src/Symfony/Component/Console/Tests/Messenger/RunCommandMessageHandlerTest.php index 58b33d5659b96..8984923741640 100644 --- a/src/Symfony/Component/Console/Tests/Messenger/RunCommandMessageHandlerTest.php +++ b/src/Symfony/Component/Console/Tests/Messenger/RunCommandMessageHandlerTest.php @@ -20,6 +20,10 @@ use Symfony\Component\Console\Messenger\RunCommandMessage; use Symfony\Component\Console\Messenger\RunCommandMessageHandler; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Messenger\Exception\RecoverableExceptionInterface; +use Symfony\Component\Messenger\Exception\RecoverableMessageHandlingException; +use Symfony\Component\Messenger\Exception\UnrecoverableExceptionInterface; +use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException; /** * @author Kevin Bond @@ -81,6 +85,38 @@ public function testThrowOnNonSuccess() $this->fail('Exception not thrown.'); } + public function testExecutesCommandThatThrownUnrecoverableException() + { + $handler = new RunCommandMessageHandler($this->createApplicationWithCommand()); + + try { + $handler(new RunCommandMessage('test:command --throw-unrecoverable')); + } catch (UnrecoverableExceptionInterface $e) { + $this->assertSame('Unrecoverable exception message', $e->getMessage()); + $this->assertNull($e->getPrevious()); + + return; + } + + $this->fail('Exception not thrown.'); + } + + public function testExecutesCommandThatThrownRecoverableException() + { + $handler = new RunCommandMessageHandler($this->createApplicationWithCommand()); + + try { + $handler(new RunCommandMessage('test:command --throw-recoverable')); + } catch (RecoverableExceptionInterface $e) { + $this->assertSame('Recoverable exception message', $e->getMessage()); + $this->assertNull($e->getPrevious()); + + return; + } + + $this->fail('Exception not thrown.'); + } + private function createApplicationWithCommand(): Application { $application = new Application(); @@ -92,6 +128,8 @@ public function configure(): void $this ->setName('test:command') ->addOption('throw') + ->addOption('throw-unrecoverable') + ->addOption('throw-recoverable') ->addOption('exit', null, InputOption::VALUE_REQUIRED, 0) ; } @@ -100,6 +138,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int { $output->write('some message'); + if ($input->getOption('throw-unrecoverable')) { + throw new UnrecoverableMessageHandlingException('Unrecoverable exception message'); + } + + if ($input->getOption('throw-recoverable')) { + throw new RecoverableMessageHandlingException('Recoverable exception message'); + } + if ($input->getOption('throw')) { throw new \RuntimeException('exception message'); } diff --git a/src/Symfony/Component/DependencyInjection/Argument/LazyClosure.php b/src/Symfony/Component/DependencyInjection/Argument/LazyClosure.php index 3e87186432efa..3dcc34e4fb61b 100644 --- a/src/Symfony/Component/DependencyInjection/Argument/LazyClosure.php +++ b/src/Symfony/Component/DependencyInjection/Argument/LazyClosure.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Argument; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Reference; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php index 9c0eec543f2d5..bbf341913e4d8 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AttributeAutoconfigurationPass.php @@ -67,14 +67,14 @@ public function process(ContainerBuilder $container): void foreach (['class', 'method', 'property', 'parameter'] as $symbol) { if (['Reflector'] !== $types) { - if (!\in_array('Reflection' . ucfirst($symbol), $types, true)) { + if (!\in_array('Reflection'.ucfirst($symbol), $types, true)) { continue; } - if (!($targets & \constant('Attribute::TARGET_' . strtoupper($symbol)))) { - throw new LogicException(\sprintf('Invalid type "Reflection%s" on argument "$%s": attribute "%s" cannot target a ' . $symbol . ' in "%s" on line "%d".', ucfirst($symbol), $reflectorParameter->getName(), $attributeName, $callableReflector->getFileName(), $callableReflector->getStartLine())); + if (!($targets & \constant('Attribute::TARGET_'.strtoupper($symbol)))) { + throw new LogicException(\sprintf('Invalid type "Reflection%s" on argument "$%s": attribute "%s" cannot target a '.$symbol.' in "%s" on line "%d".', ucfirst($symbol), $reflectorParameter->getName(), $attributeName, $callableReflector->getFileName(), $callableReflector->getStartLine())); } } - $this->{$symbol . 'AttributeConfigurators'}[$attributeName][] = $callable; + $this->{$symbol.'AttributeConfigurators'}[$attributeName][] = $callable; } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 52dc56c0f371b..8b0a804dc0d21 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -112,8 +112,8 @@ private function processDefinition(ContainerBuilder $container, string $id, Defi $definition = substr_replace($definition, '53', 2, 2); $definition = substr_replace($definition, 'Child', 44, 0); } - $definition = unserialize($definition); /** @var ChildDefinition $definition */ + $definition = unserialize($definition); $definition->setParent($parent); if (null !== $shared && !isset($definition->getChanges()['shared'])) { diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 38208124d3baf..4d1765154e249 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -823,7 +823,7 @@ public function compile(bool $resolveEnvPlaceholders = false): void if ($bag instanceof EnvPlaceholderParameterBag) { if ($resolveEnvPlaceholders) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($this->escapeParameters($bag->all()), true)); } $this->envPlaceholders = $bag->getEnvPlaceholders(); @@ -1174,7 +1174,7 @@ private function createService(Definition $definition, array &$inlineServices, b if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) { $r = new \ReflectionClass($factory[0]); - if (0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + if (0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) { trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" factory class. It should either be deprecated or its factory upgraded.', $id, $r->name); } } @@ -1191,7 +1191,7 @@ private function createService(Definition $definition, array &$inlineServices, b $service = $r->getConstructor() ? $r->newInstanceArgs($arguments) : $r->newInstance(); } - if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { + if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment() ?: '', "\n * @deprecated ")) { trigger_deprecation('', '', 'The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name); } } @@ -1500,8 +1500,8 @@ public function getAutoconfiguredAttributes(): array $autoconfiguredAttributes = []; foreach ($this->autoconfiguredAttributes as $attribute => $configurators) { - if (count($configurators) > 1) { - throw new LogicException(\sprintf('The "%s" attribute has %d configurators. Use "getAttributeAutoconfigurators()" to get all of them.', $attribute, count($configurators))); + if (\count($configurators) > 1) { + throw new LogicException(\sprintf('The "%s" attribute has %d configurators. Use "getAttributeAutoconfigurators()" to get all of them.', $attribute, \count($configurators))); } $autoconfiguredAttributes[$attribute] = $configurators[0]; @@ -1829,4 +1829,18 @@ private function inVendors(string $path): bool return $this->pathsInVendor[$path] = false; } + + private function escapeParameters(array $parameters): array + { + $params = []; + foreach ($parameters as $k => $v) { + $params[$k] = match (true) { + \is_array($v) => $this->escapeParameters($v), + \is_string($v) => str_replace('%', '%%', $v), + default => $v, + }; + } + + return $params; + } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 9568ad26b349c..fb2d45f9268ce 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -527,7 +527,7 @@ private function collectLineage(string $class, array &$lineage): void return; } $file = $r->getFileName(); - if (str_ends_with($file, ') : eval()\'d code')) { + if ($file && str_ends_with($file, ') : eval()\'d code')) { $file = substr($file, 0, strrpos($file, '(', -17)); } if (!$file || $this->doExport($file) === $exportedFile = $this->export($file)) { @@ -574,12 +574,13 @@ private function generateProxyClasses(): array continue; } do { - $file = $r->getFileName(); - if (str_ends_with($file, ') : eval()\'d code')) { - $file = substr($file, 0, strrpos($file, '(', -17)); - } - if (is_file($file)) { - $this->container->addResource(new FileResource($file)); + if ($file = $r->getFileName()) { + if (str_ends_with($file, ') : eval()\'d code')) { + $file = substr($file, 0, strrpos($file, '(', -17)); + } + if (is_file($file)) { + $this->container->addResource(new FileResource($file)); + } } $r = $r->getParentClass() ?: null; } while ($r?->isUserDefined()); diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php index 0933c1a5993f6..c534630e36ec8 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/LazyServiceDumper.php @@ -197,7 +197,7 @@ public function getProxyClass(Definition $definition, bool $asGhostObject, ?\Ref return $class->name; } - if (!$definition->hasTag('proxy') && !$class->isInterface()) { + if (!$definition->hasTag('proxy') && !$class->isAbstract()) { $parent = $class; do { $extendsInternalClass = $parent->isInternal(); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index f596980663f15..eed874cd9f6b5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -339,7 +339,11 @@ private function parseDefinition(\DOMElement $service, string $file, Definition } foreach ($this->getChildren($service, 'call') as $call) { - $definition->addMethodCall($call->getAttribute('method'), $this->getArgumentsAsPhp($call, 'argument', $file), XmlUtils::phpize($call->getAttribute('returns-clone'))); + $definition->addMethodCall( + $call->getAttribute('method'), + $this->getArgumentsAsPhp($call, 'argument', $file), + XmlUtils::phpize($call->getAttribute('returns-clone')) ?: false + ); } $tags = $this->getChildren($service, 'tag'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 5e08e47ab908c..dc33ddc418c20 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -924,6 +924,7 @@ public function testCompileWithResolveEnv() $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); $container->setParameter('foo', '%env(FOO)%'); $container->setParameter('baz', '%foo%'); + $container->setParameter('qux', '%%quux%%'); $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); $container->register('teatime', 'stdClass') ->setProperty('foo', '%env(DUMMY_ENV_VAR)%') @@ -1205,7 +1206,7 @@ public function testAddObjectResource() $this->assertCount(1, $resources); - /* @var FileResource $resource */ + /** @var FileResource $resource */ $resource = end($resources); $this->assertInstanceOf(FileResource::class, $resource); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/AbstractSayClass.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/AbstractSayClass.php new file mode 100644 index 0000000000000..f59aa1bf4a8d6 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/AbstractSayClass.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Fixtures; + +abstract class AbstractSayClass +{ + abstract public function say(): string; +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/LazyServiceInstantiatorTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/LazyServiceInstantiatorTest.php new file mode 100644 index 0000000000000..359b9824bd270 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/Instantiator/LazyServiceInstantiatorTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\LazyProxy\Instantiator; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\LazyServiceInstantiator; +use Symfony\Component\DependencyInjection\Tests\Fixtures\AbstractSayClass; + +class LazyServiceInstantiatorTest extends TestCase +{ + public function testInstantiateAbstractClassProxy() + { + $instantiator = new LazyServiceInstantiator(); + $instance = new class extends AbstractSayClass { + public int $calls = 0; + + public function say(): string + { + ++$this->calls; + + return 'Hello from the abstract class!'; + } + }; + + $definition = (new Definition(AbstractSayClass::class)) + ->setLazy(true); + + $proxy = $instantiator->instantiateProxy(new Container(), $definition, 'foo', fn () => $instance); + + $this->assertSame(0, $instance->calls); + $this->assertSame('Hello from the abstract class!', $proxy->say()); + $this->assertSame(1, $instance->calls); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/LazyServiceDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/LazyServiceDumperTest.php index 14d2f81b673ec..1d5e9b6bf2dcf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/LazyServiceDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/LazyServiceDumperTest.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyServiceDumper; +use Symfony\Component\DependencyInjection\Tests\Fixtures\AbstractSayClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\ReadOnlyClass; class LazyServiceDumperTest extends TestCase @@ -40,6 +41,16 @@ public function testFinalClassInterface() $this->assertStringContainsString('function get(', $dumper->getProxyCode($definition)); } + public function testAbstractClass() + { + $dumper = new LazyServiceDumper(); + $definition = (new Definition(AbstractSayClass::class)) + ->setLazy(true); + + $this->assertTrue($dumper->isProxyCandidate($definition)); + $this->assertNotSame(AbstractSayClass::class, $dumper->getProxyClass($definition, false)); + } + public function testInvalidClass() { $dumper = new LazyServiceDumper(); diff --git a/src/Symfony/Component/Dotenv/Command/DebugCommand.php b/src/Symfony/Component/Dotenv/Command/DebugCommand.php index 5729b94cbd8d8..b5b4f51f9703f 100644 --- a/src/Symfony/Component/Dotenv/Command/DebugCommand.php +++ b/src/Symfony/Component/Dotenv/Command/DebugCommand.php @@ -81,7 +81,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $dotenvPath = $this->projectDirectory; if (is_file($composerFile = $this->projectDirectory.'/composer.json')) { - $runtimeConfig = (json_decode(file_get_contents($composerFile), true))['extra']['runtime'] ?? []; + $runtimeConfig = json_decode(file_get_contents($composerFile), true)['extra']['runtime'] ?? []; if (isset($runtimeConfig['dotenv_path'])) { $dotenvPath = $this->projectDirectory.'/'.$runtimeConfig['dotenv_path']; diff --git a/src/Symfony/Component/Emoji/Resources/bin/build.php b/src/Symfony/Component/Emoji/Resources/bin/build.php index 0b1475bb32923..28f775baac485 100755 --- a/src/Symfony/Component/Emoji/Resources/bin/build.php +++ b/src/Symfony/Component/Emoji/Resources/bin/build.php @@ -48,7 +48,7 @@ public static function getEmojisCodePoints(): array // 263A FE0F ; fully-qualified # ☺️ E0.6 smiling face preg_match('{^(?[\w ]+) +; [\w-]+ +# (?.+) E\d+\.\d+ ?(?.+)$}Uu', $line, $matches); if (!$matches) { - throw new \DomainException("Could not parse line: \"$line\"."); + throw new DomainException("Could not parse line: \"$line\"."); } $codePoints = str_replace(' ', '-', trim($matches['codePoints'])); diff --git a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php index 2a33cee0d4353..388530762ac11 100644 --- a/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php +++ b/src/Symfony/Component/ErrorHandler/Tests/ErrorRenderer/HtmlErrorRendererTest.php @@ -100,7 +100,7 @@ public static function provideFileLinkFormats(): iterable public function testRendersStackWithoutBinaryStrings() { - // make sure method arguments are available in stack traces (see https://www.php.net/manual/en/ini.core.php) + // make sure method arguments are available in stack traces (see https://php.net/ini.core) ini_set('zend.exception_ignore_args', false); $binaryData = file_get_contents(__DIR__.'/../Fixtures/pixel.png'); diff --git a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php index 6460744ceed20..416c094ab5b48 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php @@ -141,12 +141,13 @@ private function isShortCircuited(): bool public function toArray(): array { + $nullSafe = $this->nodes['attribute'] instanceof ConstantNode && $this->nodes['attribute']->isNullSafe; switch ($this->attributes['type']) { case self::PROPERTY_CALL: - return [$this->nodes['node'], '.', $this->nodes['attribute']]; + return [$this->nodes['node'], $nullSafe ? '?.' : '.', $this->nodes['attribute']]; case self::METHOD_CALL: - return [$this->nodes['node'], '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')']; + return [$this->nodes['node'], $nullSafe ? '?.' : '.', $this->nodes['attribute'], '(', $this->nodes['arguments'], ')']; case self::ARRAY_CALL: return [$this->nodes['node'], '[', $this->nodes['attribute'], ']']; diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 624527c97a945..e8ecfc58004db 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -412,9 +412,9 @@ public function testNullSafeCompileFails($expression, $foo) public static function provideInvalidNullSafe() { - yield ['foo?.bar.baz', (object) ['bar' => null], 'Unable to get property "baz" of non-object "foo.bar".']; - yield ['foo?.bar["baz"]', (object) ['bar' => null], 'Unable to get an item of non-array "foo.bar".']; - yield ['foo?.bar["baz"].qux.quux', (object) ['bar' => ['baz' => null]], 'Unable to get property "qux" of non-object "foo.bar["baz"]".']; + yield ['foo?.bar.baz', (object) ['bar' => null], 'Unable to get property "baz" of non-object "foo?.bar".']; + yield ['foo?.bar["baz"]', (object) ['bar' => null], 'Unable to get an item of non-array "foo?.bar".']; + yield ['foo?.bar["baz"].qux.quux', (object) ['bar' => ['baz' => null]], 'Unable to get property "qux" of non-object "foo?.bar["baz"]".']; } /** diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/Node/FunctionNodeTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/Node/FunctionNodeTest.php index 36bc4e2f3de41..99994822d771f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/Node/FunctionNodeTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/Node/FunctionNodeTest.php @@ -34,7 +34,7 @@ public static function getCompileData(): array public static function getDumpData(): array { return [ - ['foo("bar")', new FunctionNode('foo', new Node([new ConstantNode('bar')])), ['foo' => static::getCallables()]], + ['foo("bar")', new FunctionNode('foo', new Node([new ConstantNode('bar')]))], ]; } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php index 6d81a2b606a60..d939afc3a643e 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/Node/GetAttrNodeTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\ExpressionLanguage\Tests\Node; +use Symfony\Component\ExpressionLanguage\Node\ArgumentsNode; use Symfony\Component\ExpressionLanguage\Node\ArrayNode; use Symfony\Component\ExpressionLanguage\Node\ConstantNode; use Symfony\Component\ExpressionLanguage\Node\GetAttrNode; @@ -50,10 +51,12 @@ public static function getDumpData(): array ['foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), self::getArrayNode(), GetAttrNode::ARRAY_CALL)], ['foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), self::getArrayNode(), GetAttrNode::ARRAY_CALL)], - ['foo.foo', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), self::getArrayNode(), GetAttrNode::PROPERTY_CALL), ['foo' => new Obj()]], + ['foo.foo', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), self::getArrayNode(), GetAttrNode::PROPERTY_CALL)], - ['foo.foo({"b": "a", 0: "b"})', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), self::getArrayNode(), GetAttrNode::METHOD_CALL), ['foo' => new Obj()]], + ['foo.foo({"b": "a", 0: "b"})', new GetAttrNode(new NameNode('foo'), new NameNode('foo'), self::getArrayNode(), GetAttrNode::METHOD_CALL)], ['foo[index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), self::getArrayNode(), GetAttrNode::ARRAY_CALL)], + + ['foo?.foo()', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo', true, true), new ArgumentsNode(), GetAttrNode::METHOD_CALL)], ]; } diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index f97c8b2fe56ed..bfe3878030b36 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -225,7 +225,7 @@ public function chmod(string|iterable $files, int $mode, int $umask = 0000, bool * * This method always throws on Windows, as the underlying PHP function is not supported. * - * @see https://www.php.net/chown + * @see https://php.net/chown * * @param string|int $user A user name or number * @param bool $recursive Whether change the owner recursively or not @@ -255,7 +255,7 @@ public function chown(string|iterable $files, string|int $user, bool $recursive * * This method always throws on Windows, as the underlying PHP function is not supported. * - * @see https://www.php.net/chgrp + * @see https://php.net/chgrp * * @param string|int $group A group name or number * @param bool $recursive Whether change the group recursively or not diff --git a/src/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php index 34ba50ddcf0d0..578b34d09ec7e 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/FilecontentFilterIteratorTest.php @@ -72,7 +72,7 @@ public static function getTestFilterData() $inner[] = new MockSplFileInfo([ 'name' => 'unreadable-file.txt', - 'contents' => false, + 'contents' => '', 'type' => 'file', 'mode' => 'r+', ] ); diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index ffcbc1feee6d7..b0f48a44c80b6 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -185,6 +185,10 @@ protected function castParsedValue(int|float $value): int|float */ private function round(int|float $number): int|float { + if (\is_int($number)) { + return $number; + } + if (null !== $this->scale) { // shift number to maintain the correct scale during rounding $roundingCoef = 10 ** $this->scale; diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 8f4ec60f24a86..7f8a728dd112b 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -39,7 +39,7 @@ public function validate(mixed $form, Constraint $formConstraint): void return; } - /* @var FormInterface $form */ + /** @var FormInterface $form */ $config = $form->getConfig(); $validator = $this->context->getValidator()->inContext($this->context); diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php index 2c534481cd6ee..9cc19c356aefb 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php +++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorExtension.php @@ -40,7 +40,7 @@ public function __construct( // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml - /* @var ClassMetadata $metadata */ + /** @var ClassMetadata $metadata */ $metadata->addConstraint(new Form()); $metadata->addConstraint(new Traverse(false)); } diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php index faca255b5dcbb..c6ef92bf3a413 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -248,7 +248,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ // Test mapping rules as long as we have any foreach ($rules as $key => $rule) { - /* @var MappingRule $rule */ + /** @var MappingRule $rule */ // Mapping rule matches completely, terminate. if (null !== ($form = $rule->match($chunk))) { @@ -312,7 +312,7 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } else { - /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ + /** @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 4f4a2574d2dce..d207bb1a59ef8 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -76,7 +76,7 @@ public function __toString(): string if ($error instanceof FormError) { $string .= 'ERROR: '.$error->getMessage()."\n"; } else { - /* @var self $error */ + /** @var self $error */ $string .= $error->getForm()->getName().":\n"; $string .= self::indent((string) $error); } diff --git a/src/Symfony/Component/Form/ResolvedFormType.php b/src/Symfony/Component/Form/ResolvedFormType.php index 82065f651144f..81c9c396de440 100644 --- a/src/Symfony/Component/Form/ResolvedFormType.php +++ b/src/Symfony/Component/Form/ResolvedFormType.php @@ -118,7 +118,7 @@ public function finishView(FormView $view, FormInterface $form, array $options): $this->innerType->finishView($view, $form, $options); foreach ($this->typeExtensions as $extension) { - /* @var FormTypeExtensionInterface $extension */ + /** @var FormTypeExtensionInterface $extension */ $extension->finishView($view, $form, $options); } } diff --git a/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf b/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf index 76df58246b328..dbf9ea8320171 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.ca.xlf @@ -8,87 +8,87 @@ The uploaded file was too large. Please try to upload a smaller file. - L'arxiu pujat és massa gran. Per favor, pugi un arxiu més petit. + El fitxer pujat és massa gran. Pujeu un fitxer més petit. The CSRF token is invalid. Please try to resubmit the form. - El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. + El token CSRF no és vàlid. Torneu a enviar el formulari. This value is not a valid HTML5 color. - Aquest valor no és un color HTML5 valid. + Aquest valor no és un color HTML5 vàlid. Please enter a valid birthdate. - Per favor introdueix una data d'aniversari valida. + Introduïu una data d'aniversari vàlida. The selected choice is invalid. - L'opció escollida és invalida. + L'opció escollida no és vàlida. The collection is invalid. - La col·lecció és invalida. + La col·lecció no és vàlida. Please select a valid color. - Per favor selecciona un color vàlid. + Seleccioneu un color vàlid. Please select a valid country. - Per favor selecciona una ciutat vàlida. + Seleccioneu una ciutat vàlida. Please select a valid currency. - Per favor selecciona una moneda vàlida. + Seleccioneu una moneda vàlida. Please choose a valid date interval. - Per favor escull un interval de dates vàlides. + Escolliu un interval de dates vàlides. Please enter a valid date and time. - Per favor introdueix una data i temps vàlid. + Introduïu una data i hora vàlides. Please enter a valid date. - Per favor introdueix una data vàlida. + Introduïu una data vàlida. Please select a valid file. - Per favor selecciona un arxiu vàlid. + Seleccioneu un fitxer vàlid. The hidden field is invalid. - El camp ocult és invàlid. + El camp ocult no és vàlid. Please enter an integer. - Per favor introdueix un enter. + Introduïu un enter. Please select a valid language. - Per favor selecciona un idioma vàlid. + Seleccioneu un idioma vàlid. Please select a valid locale. - Per favor seleccioneu una configuració regional vàlida + Seleccioneu una configuració regional vàlida Please enter a valid money amount. - Per favor introdueix una quantitat de diners vàlids. + Introduïu una quantitat de diners vàlida. Please enter a number. - Per favor introdueix un número. + Introduïu un número. The password is invalid. - La contrasenya es invàlida. + La contrasenya no és vàlida. Please enter a percentage value. - Per favor introdueix un valor percentual. + Introduïu un valor percentual. The values do not match. @@ -96,43 +96,43 @@ Please enter a valid time. - Per favor introdueix un temps vàlid. + Introduïu una hora vàlida. Please select a valid timezone. - Per favor selecciona una zona horària vàlida. + Seleccioneu una zona horària vàlida. Please enter a valid URL. - Per favor introdueix una URL vàlida. + Introduïu una URL vàlida. Please enter a valid search term. - Per favor introdueix un concepte de cerca vàlid. + Introduïu un terme de cerca vàlid. Please provide a valid phone number. - Per favor introdueix un número de telèfon vàlid. + Introduïu un número de telèfon vàlid. The checkbox has an invalid value. - La casella de selecció te un valor invàlid. + La casella de selecció te un valor no vàlid. Please enter a valid email address. - Per favor introdueix un correu electrònic vàlid. + Introduïu un correu electrònic vàlid. Please select a valid option. - Per favor selecciona una opció vàlida. + Seleccioneu una opció vàlida. Please select a valid range. - Per favor selecciona un rang vàlid. + Seleccioneu un rang vàlid. Please enter a valid week. - Per favor introdueix una setmana vàlida. + Introduïu una setmana vàlida. diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index c0344b9f232ea..fbb1030457ce3 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -726,4 +726,40 @@ public static function eNotationProvider(): array [1232.0, '1.232e3'], ]; } + + public function testReverseTransformDoesNotCauseIntegerPrecisionLoss() + { + if (\PHP_INT_SIZE === 4) { + $this->markTestSkipped('Test is not applicable on 32-bit systems where no integer loses precision when cast to float.'); + } + + $transformer = new NumberToLocalizedStringTransformer(); + + // Test a large integer that causes actual precision loss when cast to float + $largeInt = \PHP_INT_MAX - 1; // This value loses precision when cast to float + $result = $transformer->reverseTransform((string) $largeInt); + + $this->assertSame($largeInt, $result); + $this->assertIsInt($result); + } + + public function testRoundMethodKeepsIntegersAsIntegers() + { + if (\PHP_INT_SIZE === 4) { + $this->markTestSkipped('Test is not applicable on 32-bit systems where no integer loses precision when cast to float.'); + } + + $transformer = new NumberToLocalizedStringTransformer(2); // scale=2 triggers rounding + + // Use reflection to test the private round() method directly + $reflection = new \ReflectionClass($transformer); + $roundMethod = $reflection->getMethod('round'); + + $int = \PHP_INT_MAX - 1; + $result = $roundMethod->invoke($transformer, $int); + + // With the fix, integers should stay as integers, not be converted to floats + $this->assertSame($int, $result); + $this->assertIsInt($result); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php index 44073ef7b9333..171a7491bfaa7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php @@ -21,7 +21,7 @@ class CountryTypeTest extends BaseTypeTestCase protected function setUp(): void { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); parent::setUp(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php index 3e8a53dfb20ee..e5a1403921d4b 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -21,7 +21,7 @@ class CurrencyTypeTest extends BaseTypeTestCase protected function setUp(): void { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); parent::setUp(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php index ff33c17c63cf1..9a689d58f8271 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -22,7 +22,7 @@ class IntegerTypeTest extends BaseTypeTestCase protected function setUp(): void { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); $this->previousLocale = \Locale::getDefault(); parent::setUp(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php index 8eb085112fbf3..50bd373a0f010 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -22,7 +22,7 @@ class LanguageTypeTest extends BaseTypeTestCase protected function setUp(): void { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); parent::setUp(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php index a2a820b390911..381cc55beca26 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -21,7 +21,7 @@ class LocaleTypeTest extends BaseTypeTestCase protected function setUp(): void { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); parent::setUp(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php index 4f234397464f9..1c37229be12ea 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -144,7 +144,7 @@ public function testIntlTimeZoneInputWithBcAndIntl() public function testTimezonesAreSelectableWithIntl() { - IntlTestHelper::requireIntl($this, false); + IntlTestHelper::requireIntl($this); $choices = $this->factory->create(static::TESTED_TYPE, null, ['intl' => true]) ->createView()->vars['choices']; diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index d5d3549d2a8f6..0f9a6dc41c6a6 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -1052,7 +1052,7 @@ public function testInitializeSetsDefaultData() $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); $form = new Form($config); - /* @var Form $form */ + /** @var Form $form */ $form->initialize(); $this->assertSame('DEFAULT', $form->getData()); diff --git a/src/Symfony/Component/HttpClient/Response/AmpResponseV4.php b/src/Symfony/Component/HttpClient/Response/AmpResponseV4.php index 31ea22d0a63bf..e1fc1197e6070 100644 --- a/src/Symfony/Component/HttpClient/Response/AmpResponseV4.php +++ b/src/Symfony/Component/HttpClient/Response/AmpResponseV4.php @@ -224,7 +224,7 @@ private static function generateResponse(Request $request, AmpClientStateV4 $mul }); try { - /* @var Response $response */ + /** @var Response $response */ if (null === $response = yield from self::getPushedResponse($request, $multi, $info, $headers, $options, $logger)) { $logger?->info(\sprintf('Request: "%s %s"', $info['http_method'], $info['url'])); diff --git a/src/Symfony/Component/HttpClient/Response/AmpResponseV5.php b/src/Symfony/Component/HttpClient/Response/AmpResponseV5.php index 8f56c76a41033..7fc1036d4c34e 100644 --- a/src/Symfony/Component/HttpClient/Response/AmpResponseV5.php +++ b/src/Symfony/Component/HttpClient/Response/AmpResponseV5.php @@ -240,6 +240,10 @@ private static function generateResponse(Request $request, AmpClientStateV5 $mul $body = $response->getBody(); while (true) { + if (!isset($multi->openHandles[$id])) { + return; + } + $multi->openHandles[$id]->complete(); $multi->openHandles[$id] = new DeferredFuture(); diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php index 76969a3238c39..f76b52c442ce2 100644 --- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php @@ -512,7 +512,7 @@ public function testUnixSocket() public function testChangeResponseFactory() { - /* @var MockHttpClient $client */ + /** @var MockHttpClient $client */ $client = $this->getHttpClient(__METHOD__); $expectedBody = '{"foo": "bar"}'; $client->setResponseFactory(new MockResponse($expectedBody)); diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 11a43238b4601..f67e314ab7ee0 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -196,7 +196,7 @@ public static function anonymize(string $ip/* , int $v4Bytes = 1, int $v6Bytes = throw new \InvalidArgumentException('Cannot anonymize more than 4 bytes for IPv4 and 16 bytes for IPv6.'); } - /** + /* * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007 * In that case, we only care about the part before the % symbol, as the following functions, can only work with * the IP address itself. As the scope can leak information (containing interface name), we do not want to diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 3d08f5f6d7c01..5c08513477269 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -123,7 +123,7 @@ public function start(): bool * ---------- Part 1 * * The part `[a-zA-Z0-9,-]` is related to the PHP ini directive `session.sid_bits_per_character` defined as 6. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-bits-per-character. + * See https://php.net/session.configuration#ini.session.sid-bits-per-character * Allowed values are integers such as: * - 4 for range `a-f0-9` * - 5 for range `a-v0-9` (@deprecated since Symfony 7.2, it will default to 4 and the option will be ignored in Symfony 8.0) @@ -132,7 +132,7 @@ public function start(): bool * ---------- Part 2 * * The part `{22,250}` is related to the PHP ini directive `session.sid_length`. - * See https://www.php.net/manual/en/session.configuration.php#ini.session.sid-length. + * See https://php.net/session.configuration#ini.session.sid-length * Allowed values are integers between 22 and 256, but we use 250 for the max. * * Where does the 250 come from? diff --git a/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php index fdaee3a35ff6f..584353b7f9811 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/StreamedResponseTest.php @@ -32,7 +32,7 @@ public function testConstructorWithChunks() $buffer = ''; ob_start(function (string $chunk) use (&$buffer) { - $buffer .= $chunk; + return $buffer .= $chunk; }); $callback(); diff --git a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php index 2599b27de0c97..81f5dfb7fc953 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php @@ -164,13 +164,13 @@ public static function getSubscribedEvents(): array * * @param ?string $logChannel */ - protected function logException(\Throwable $exception, string $message, ?string $logLevel = null, /* ?string $logChannel = null */): void + protected function logException(\Throwable $exception, string $message, ?string $logLevel = null/* , ?string $logChannel = null */): void { - $logChannel = (3 < \func_num_args() ? \func_get_arg(3) : null) ?? $this->resolveLogChannel($exception); + $logChannel = (3 < \func_num_args() ? func_get_arg(3) : null) ?? $this->resolveLogChannel($exception); $logLevel ??= $this->resolveLogLevel($exception); - if(!$logger = $this->getLogger($logChannel)) { + if (!$logger = $this->getLogger($logChannel)) { return; } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4829bfb7dedc7..d8be61d6c6f91 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -73,11 +73,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '7.3.1'; - public const VERSION_ID = 70301; + public const VERSION = '7.3.2'; + public const VERSION_ID = 70302; public const MAJOR_VERSION = 7; public const MINOR_VERSION = 3; - public const RELEASE_VERSION = 1; + public const RELEASE_VERSION = 2; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '01/2026'; diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php index ca7bb1b1f6d9e..f980984943005 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php @@ -354,7 +354,7 @@ public static function provideRouteMapping(): iterable '_route_mapping' => [ 'id' => [ 'article', - 'id' + 'id', ], 'date' => [ 'article', diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php index deba6661f0de8..fda957bb4998a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php @@ -104,13 +104,13 @@ public static function provideSessionOptions(): \Generator yield 'set_cookiesecure_auto_by_symfony_false_by_php' => [ 'phpSessionOptions' => ['secure' => false], - 'sessionOptions' => ['cookie_path' => '/test/', 'cookie_httponly' => 'auto', 'cookie_secure' => 'auto', 'cookie_samesite' => Cookie::SAMESITE_LAX], + 'sessionOptions' => ['cookie_path' => '/test/', 'cookie_httponly' => true, 'cookie_secure' => 'auto', 'cookie_samesite' => Cookie::SAMESITE_LAX], 'expectedSessionOptions' => ['cookie_path' => '/test/', 'cookie_domain' => '', 'cookie_secure' => false, 'cookie_httponly' => true, 'cookie_samesite' => Cookie::SAMESITE_LAX], ]; yield 'set_cookiesecure_auto_by_symfony_true_by_php' => [ 'phpSessionOptions' => ['secure' => true], - 'sessionOptions' => ['cookie_path' => '/test/', 'cookie_httponly' => 'auto', 'cookie_secure' => 'auto', 'cookie_samesite' => Cookie::SAMESITE_LAX], + 'sessionOptions' => ['cookie_path' => '/test/', 'cookie_httponly' => true, 'cookie_secure' => 'auto', 'cookie_samesite' => Cookie::SAMESITE_LAX], 'expectedSessionOptions' => ['cookie_path' => '/test/', 'cookie_domain' => '', 'cookie_secure' => true, 'cookie_httponly' => true, 'cookie_samesite' => Cookie::SAMESITE_LAX], ]; diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index 240b201306d92..9f03f6d8e857c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -714,7 +714,7 @@ public function testHitBackendOnlyOnceWhenCacheWasLocked() $this->request('GET', '/'); // warm the cache // Use a store that simulates a cache entry being locked upon first attempt - $this->store = new class(sys_get_temp_dir() . '/http_cache') extends Store { + $this->store = new class(sys_get_temp_dir().'/http_cache') extends Store { private bool $hasLock = false; public function lock(Request $request): bool diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php index 88f6bed56f4cf..b05d9136661c3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTestCase.php @@ -115,7 +115,7 @@ public function request($method, $uri = '/', $server = [], $cookies = [], $esi = $this->kernel->reset(); - if (! $this->store) { + if (!$this->store) { $this->store = $this->createStore(); } @@ -188,6 +188,6 @@ public static function clearDirectory($directory) protected function createStore(): Store { - return new Store(sys_get_temp_dir() . '/http_cache'); + return new Store(sys_get_temp_dir().'/http_cache'); } } diff --git a/src/Symfony/Component/Intl/Tests/CountriesTest.php b/src/Symfony/Component/Intl/Tests/CountriesTest.php index 01f0f76f2e40a..285dad8fd1e13 100644 --- a/src/Symfony/Component/Intl/Tests/CountriesTest.php +++ b/src/Symfony/Component/Intl/Tests/CountriesTest.php @@ -780,10 +780,10 @@ class CountriesTest extends ResourceBundleTestCase public function testAllGettersGenerateTheSameDataSetCount() { - $alpha2Count = count(Countries::getCountryCodes()); - $alpha3Count = count(Countries::getAlpha3Codes()); - $numericCodesCount = count(Countries::getNumericCodes()); - $namesCount = count(Countries::getNames()); + $alpha2Count = \count(Countries::getCountryCodes()); + $alpha3Count = \count(Countries::getAlpha3Codes()); + $numericCodesCount = \count(Countries::getNumericCodes()); + $namesCount = \count(Countries::getNames()); // we base all on Name count since it is the first to be generated $this->assertEquals($namesCount, $alpha2Count, 'Alpha 2 count does not match'); diff --git a/src/Symfony/Component/JsonPath/JsonCrawler.php b/src/Symfony/Component/JsonPath/JsonCrawler.php index 0793a5c5d7b14..8e2b32f3452e7 100644 --- a/src/Symfony/Component/JsonPath/JsonCrawler.php +++ b/src/Symfony/Component/JsonPath/JsonCrawler.php @@ -12,6 +12,7 @@ namespace Symfony\Component\JsonPath; use Symfony\Component\JsonPath\Exception\InvalidArgumentException; +use Symfony\Component\JsonPath\Exception\InvalidJsonPathException; use Symfony\Component\JsonPath\Exception\InvalidJsonStringInputException; use Symfony\Component\JsonPath\Exception\JsonCrawlerException; use Symfony\Component\JsonPath\Tokenizer\JsonPathToken; @@ -83,7 +84,7 @@ private function evaluate(JsonPath $query): array return $this->evaluateTokensOnDecodedData($tokens, $data); } catch (InvalidArgumentException $e) { throw $e; - } catch (\Throwable $e) { + } catch (InvalidJsonPathException $e) { throw new JsonCrawlerException($query, $e->getMessage(), previous: $e); } } @@ -143,6 +144,10 @@ private function evaluateBracket(string $expr, mixed $value): array // single negative index if (preg_match('/^-\d+$/', $expr)) { + if (JsonPathUtils::hasLeadingZero($expr) || JsonPathUtils::isIntegerOverflow($expr) || '-0' === $expr) { + throw new JsonCrawlerException($expr, 'invalid index selector'); + } + if (!array_is_list($value)) { return []; } @@ -154,6 +159,12 @@ private function evaluateBracket(string $expr, mixed $value): array // start and end index if (preg_match('/^-?\d+(?:\s*,\s*-?\d+)*$/', $expr)) { + foreach (explode(',', $expr) as $exprPart) { + if (JsonPathUtils::hasLeadingZero($exprPart = trim($exprPart)) || JsonPathUtils::isIntegerOverflow($exprPart) || '-0' === $exprPart) { + throw new JsonCrawlerException($expr, 'invalid index selector'); + } + } + if (!array_is_list($value)) { return []; } @@ -172,17 +183,41 @@ private function evaluateBracket(string $expr, mixed $value): array return $result; } - if (preg_match('/^(-?\d*+)\s*+:\s*+(-?\d*+)(?:\s*+:\s*+(-?\d++))?$/', $expr, $matches)) { + if (preg_match('/^(-?\d*+)\s*+:\s*+(-?\d*+)(?:\s*+:\s*+(-?\d*+))?$/', $expr, $matches)) { if (!array_is_list($value)) { return []; } + $startStr = trim($matches[1]); + $endStr = trim($matches[2]); + $stepStr = trim($matches[3] ?? '1'); + + if ( + JsonPathUtils::hasLeadingZero($startStr) + || JsonPathUtils::hasLeadingZero($endStr) + || JsonPathUtils::hasLeadingZero($stepStr) + ) { + throw new JsonCrawlerException($expr, 'slice selector numbers cannot have leading zeros'); + } + + if ('-0' === $startStr || '-0' === $endStr || '-0' === $stepStr) { + throw new JsonCrawlerException($expr, 'slice selector cannot contain negative zero'); + } + + if ( + JsonPathUtils::isIntegerOverflow($startStr) + || JsonPathUtils::isIntegerOverflow($endStr) + || JsonPathUtils::isIntegerOverflow($stepStr) + ) { + throw new JsonCrawlerException($expr, 'slice selector integer overflow'); + } + $length = \count($value); - $start = '' !== $matches[1] ? (int) $matches[1] : null; - $end = '' !== $matches[2] ? (int) $matches[2] : null; - $step = isset($matches[3]) && '' !== $matches[3] ? (int) $matches[3] : 1; + $start = '' !== $startStr ? (int) $startStr : null; + $end = '' !== $endStr ? (int) $endStr : null; + $step = '' !== $stepStr ? (int) $stepStr : 1; - if (0 === $step || $start > $length) { + if (0 === $step) { return []; } @@ -192,6 +227,11 @@ private function evaluateBracket(string $expr, mixed $value): array if ($start < 0) { $start = $length + $start; } + + if ($step > 0 && $start >= $length) { + return []; + } + $start = max(0, min($start, $length - 1)); } @@ -290,7 +330,7 @@ private function evaluateBracket(string $expr, mixed $value): array return \array_key_exists($key, $value) ? [$value[$key]] : []; } - throw new \LogicException(\sprintf('Unsupported bracket expression "%s".', $expr)); + throw new InvalidJsonPathException(\sprintf('Unsupported bracket expression "%s".', $expr)); } private function evaluateFilter(string $expr, mixed $value): array diff --git a/src/Symfony/Component/JsonPath/JsonPathUtils.php b/src/Symfony/Component/JsonPath/JsonPathUtils.php index 30bf446b6a9d5..18134c23d3ea6 100644 --- a/src/Symfony/Component/JsonPath/JsonPathUtils.php +++ b/src/Symfony/Component/JsonPath/JsonPathUtils.php @@ -12,6 +12,7 @@ namespace Symfony\Component\JsonPath; use Symfony\Component\JsonPath\Exception\InvalidArgumentException; +use Symfony\Component\JsonPath\Exception\JsonCrawlerException; use Symfony\Component\JsonPath\Tokenizer\JsonPathToken; use Symfony\Component\JsonPath\Tokenizer\TokenType; use Symfony\Component\JsonStreamer\Read\Splitter; @@ -86,6 +87,9 @@ public static function findSmallestDeserializableStringAndPath(array $tokens, mi ]; } + /** + * @throws JsonCrawlerException When an invalid Unicode escape sequence occurs + */ public static function unescapeString(string $str, string $quoteChar): string { if ('"' === $quoteChar) { @@ -104,17 +108,16 @@ public static function unescapeString(string $str, string $quoteChar): string while (null !== $char = $str[++$i] ?? null) { if ('\\' === $char && isset($str[$i + 1])) { $result .= match ($str[$i + 1]) { - '"' => '"', - "'" => "'", '\\' => '\\', '/' => '/', - 'b' => "\b", + 'b' => "\x08", 'f' => "\f", 'n' => "\n", 'r' => "\r", 't' => "\t", 'u' => self::unescapeUnicodeSequence($str, $i), - default => $char.$str[$i + 1], // keep the backslash + $quoteChar => $quoteChar, + default => throw new JsonCrawlerException('', \sprintf('Invalid escape sequence "\\%s" in %s-quoted string.', $str[$i + 1], "'" === $quoteChar ? 'single' : 'double')), }; ++$i; @@ -128,36 +131,34 @@ public static function unescapeString(string $str, string $quoteChar): string private static function unescapeUnicodeSequence(string $str, int &$i): string { - if (!isset($str[$i + 5])) { - // not enough characters for Unicode escape, treat as literal - return $str[$i]; + if (!isset($str[$i + 5]) || !ctype_xdigit(substr($str, $i + 2, 4))) { + throw new JsonCrawlerException('', 'Invalid unicode escape sequence.'); } - $hex = substr($str, $i + 2, 4); - if (!ctype_xdigit($hex)) { - // invalid hex, treat as literal - return $str[$i]; - } + $codepoint = hexdec(substr($str, $i + 2, 4)); - $codepoint = hexdec($hex); // looks like a valid Unicode codepoint, string length is sufficient and it starts with \u - if (0xD800 <= $codepoint && $codepoint <= 0xDBFF && isset($str[$i + 11]) && '\\' === $str[$i + 6] && 'u' === $str[$i + 7]) { - $lowHex = substr($str, $i + 8, 4); - if (ctype_xdigit($lowHex)) { - $lowSurrogate = hexdec($lowHex); - if (0xDC00 <= $lowSurrogate && $lowSurrogate <= 0xDFFF) { - $codepoint = 0x10000 + (($codepoint & 0x3FF) << 10) + ($lowSurrogate & 0x3FF); - $i += 10; // skip surrogate pair - - return mb_chr($codepoint, 'UTF-8'); - } - } + if (0xD800 <= $codepoint + && $codepoint <= 0xDBFF + && isset($str[$i + 11]) + && '\\' === $str[$i + 6] + && 'u' === $str[$i + 7] + && ctype_xdigit($lowSurrogate = substr($str, $i + 8, 4)) + && 0xDC00 <= ($lowSurrogate = hexdec($lowSurrogate)) + && $lowSurrogate <= 0xDFFF + ) { + $codepoint = 0x10000 + (($codepoint & 0x3FF) << 10) + ($lowSurrogate & 0x3FF); + $i += 10; // skip surrogate pair + } else { + // single Unicode character or invalid surrogate, skip the sequence + $i += 4; } - // single Unicode character or invalid surrogate, skip the sequence - $i += 4; + if (false === $chr = mb_chr($codepoint, 'UTF-8')) { + throw new JsonCrawlerException('', \sprintf('Invalid Unicode codepoint: U+%04X.', $codepoint)); + } - return mb_chr($codepoint, 'UTF-8'); + return $chr; } /** @@ -227,4 +228,39 @@ public static function parseCommaSeparatedValues(string $expr): array return $parts; } + + public static function hasLeadingZero(string $s): bool + { + if ('' === $s || str_starts_with($s, '-') && '' === $s = substr($s, 1)) { + return false; + } + + return '0' === $s[0] && 1 < \strlen($s); + } + + /** + * Safe integer range is [-(2^53) + 1, (2^53) - 1]. + * + * @see https://datatracker.ietf.org/doc/rfc9535/, section 2.1 + */ + public static function isIntegerOverflow(string $s): bool + { + if ('' === $s) { + return false; + } + + $negative = str_starts_with($s, '-'); + $maxLength = $negative ? 17 : 16; + $len = \strlen($s); + + if ($len > $maxLength) { + return true; + } + + if ($len < $maxLength) { + return false; + } + + return $negative ? $s < '-9007199254740991' : $s > '9007199254740991'; + } } diff --git a/src/Symfony/Component/JsonPath/README.md b/src/Symfony/Component/JsonPath/README.md index 1a15a7111b2ed..ac900623b8ef5 100644 --- a/src/Symfony/Component/JsonPath/README.md +++ b/src/Symfony/Component/JsonPath/README.md @@ -35,7 +35,7 @@ $result = $crawler->find("$.store.book[?(@.category == 'fiction')].title"); Resources --------- - * [Documentation](https://symfony.com/doc/current/components/dom_crawler.html) + * [Documentation](https://symfony.com/doc/current/components/json_path.html) * [Contributing](https://symfony.com/doc/current/contributing/index.html) * [Report issues](https://github.com/symfony/symfony/issues) and [send Pull Requests](https://github.com/symfony/symfony/pulls) diff --git a/src/Symfony/Component/JsonPath/Tests/JsonCrawlerTest.php b/src/Symfony/Component/JsonPath/Tests/JsonCrawlerTest.php index 1d1eb4be3b431..b1357d7f31ee6 100644 --- a/src/Symfony/Component/JsonPath/Tests/JsonCrawlerTest.php +++ b/src/Symfony/Component/JsonPath/Tests/JsonCrawlerTest.php @@ -86,7 +86,7 @@ public function testEscapedDoubleQuotesInFieldName() {"a": {"b\\"c": 42}} JSON); - $result = $crawler->find("$['a']['b\\\"c']"); + $result = $crawler->find('$["a"]["b\"c"]'); $this->assertSame(42, $result[0]); } @@ -641,10 +641,6 @@ public static function provideSingleQuotedStringProvider(): array "$['\\u65e5\\u672c']", ['Japan'], ], - [ - "$['quote\"here']", - ['with quote'], - ], [ "$['M\\u00fcller']", [], @@ -658,7 +654,7 @@ public static function provideSingleQuotedStringProvider(): array ['with tab'], ], [ - "$['quote\\\"here']", + "$['quote\"here']", ['with quote'], ], [ @@ -725,29 +721,6 @@ public static function provideFilterWithUnicodeProvider(): array ]; } - /** - * @dataProvider provideInvalidUnicodeSequenceProvider - */ - public function testInvalidUnicodeSequencesAreProcessedAsLiterals(string $jsonPath) - { - $this->assertIsArray(self::getUnicodeDocumentCrawler()->find($jsonPath), 'invalid unicode sequence should be treated as literal and not throw'); - } - - public static function provideInvalidUnicodeSequenceProvider(): array - { - return [ - [ - '$["test\uZZZZ"]', - ], - [ - '$["test\u123"]', - ], - [ - '$["test\u"]', - ], - ]; - } - /** * @dataProvider provideComplexUnicodePath */ diff --git a/src/Symfony/Component/JsonPath/Tests/JsonPathComplianceTestSuiteTest.php b/src/Symfony/Component/JsonPath/Tests/JsonPathComplianceTestSuiteTest.php index b39b68abcd463..a3454e6b94617 100644 --- a/src/Symfony/Component/JsonPath/Tests/JsonPathComplianceTestSuiteTest.php +++ b/src/Symfony/Component/JsonPath/Tests/JsonPathComplianceTestSuiteTest.php @@ -103,11 +103,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase 'filter, group terms, right', 'name selector, double quotes, escaped reverse solidus', 'name selector, single quotes, escaped reverse solidus', - 'slice selector, slice selector with everything omitted, long form', - 'slice selector, start, min exact', - 'slice selector, start, max exact', - 'slice selector, end, min exact', - 'slice selector, end, max exact', 'basic, descendant segment, multiple selectors', 'basic, bald descendant segment', 'filter, relative non-singular query, index, equal', @@ -142,48 +137,6 @@ final class JsonPathComplianceTestSuiteTest extends TestCase 'filter, absolute non-singular query, slice, less-or-equal', 'filter, equals, special nothing', 'filter, group terms, left', - 'index selector, min exact index - 1', - 'index selector, max exact index + 1', - 'index selector, overflowing index', - 'index selector, leading 0', - 'index selector, -0', - 'index selector, leading -0', - 'name selector, double quotes, escaped line feed', - 'name selector, double quotes, invalid escaped single quote', - 'name selector, double quotes, question mark escape', - 'name selector, double quotes, bell escape', - 'name selector, double quotes, vertical tab escape', - 'name selector, double quotes, 0 escape', - 'name selector, double quotes, x escape', - 'name selector, double quotes, n escape', - 'name selector, double quotes, unicode escape no hex', - 'name selector, double quotes, unicode escape too few hex', - 'name selector, double quotes, unicode escape upper u', - 'name selector, double quotes, unicode escape upper u long', - 'name selector, double quotes, unicode escape plus', - 'name selector, double quotes, unicode escape brackets', - 'name selector, double quotes, unicode escape brackets long', - 'name selector, double quotes, single high surrogate', - 'name selector, double quotes, single low surrogate', - 'name selector, double quotes, high high surrogate', - 'name selector, double quotes, low low surrogate', - 'name selector, double quotes, supplementary surrogate', - 'name selector, double quotes, surrogate incomplete low', - 'name selector, single quotes, escaped backspace', - 'name selector, single quotes, escaped line feed', - 'name selector, single quotes, invalid escaped double quote', - 'slice selector, excessively large from value with negative step', - 'slice selector, step, min exact - 1', - 'slice selector, step, max exact + 1', - 'slice selector, overflowing to value', - 'slice selector, underflowing from value', - 'slice selector, overflowing from value with negative step', - 'slice selector, underflowing to value with negative step', - 'slice selector, overflowing step', - 'slice selector, underflowing step', - 'slice selector, step, leading 0', - 'slice selector, step, -0', - 'slice selector, step, leading -0', ]; /** diff --git a/src/Symfony/Component/JsonStreamer/DataModel/Write/CollectionNode.php b/src/Symfony/Component/JsonStreamer/DataModel/Write/CollectionNode.php index 2f324fb404908..309c6026aec9d 100644 --- a/src/Symfony/Component/JsonStreamer/DataModel/Write/CollectionNode.php +++ b/src/Symfony/Component/JsonStreamer/DataModel/Write/CollectionNode.php @@ -27,12 +27,13 @@ public function __construct( private DataAccessorInterface $accessor, private CollectionType $type, private DataModelNodeInterface $item, + private DataModelNodeInterface $key, ) { } public function withAccessor(DataAccessorInterface $accessor): self { - return new self($accessor, $this->type, $this->item); + return new self($accessor, $this->type, $this->item, $this->key); } public function getIdentifier(): string @@ -54,4 +55,9 @@ public function getItemNode(): DataModelNodeInterface { return $this->item; } + + public function getKeyNode(): DataModelNodeInterface + { + return $this->key; + } } diff --git a/src/Symfony/Component/JsonStreamer/Tests/DataModel/Write/CompositeNodeTest.php b/src/Symfony/Component/JsonStreamer/Tests/DataModel/Write/CompositeNodeTest.php index a7ef7df343d6f..65a16c9653572 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/DataModel/Write/CompositeNodeTest.php +++ b/src/Symfony/Component/JsonStreamer/Tests/DataModel/Write/CompositeNodeTest.php @@ -49,7 +49,7 @@ public function testSortNodesOnCreation() $composite = new CompositeNode(new VariableDataAccessor('data'), [ $scalar = new ScalarNode(new VariableDataAccessor('data'), Type::int()), $object = new ObjectNode(new VariableDataAccessor('data'), Type::object(self::class), []), - $collection = new CollectionNode(new VariableDataAccessor('data'), Type::list(), new ScalarNode(new VariableDataAccessor('data'), Type::int())), + $collection = new CollectionNode(new VariableDataAccessor('data'), Type::list(), new ScalarNode(new VariableDataAccessor('data'), Type::int()), new ScalarNode(new VariableDataAccessor('key'), Type::string())), ]); $this->assertSame([$collection, $object, $scalar], $composite->getNodes()); diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/Model/DummyWithArray.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/Model/DummyWithArray.php new file mode 100644 index 0000000000000..e47f057fd7bc1 --- /dev/null +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/Model/DummyWithArray.php @@ -0,0 +1,11 @@ +dummies as $value2) { + yield $prefix; + yield '{"dummies":['; + $prefix = ''; + foreach ($value2->dummies as $value3) { + yield $prefix; + yield '{"id":'; + yield \json_encode($value3->id, \JSON_THROW_ON_ERROR, 506); + yield ',"name":'; + yield \json_encode($value3->name, \JSON_THROW_ON_ERROR, 506); + yield '}'; + $prefix = ','; + } + yield '],"customProperty":'; + yield \json_encode($value2->customProperty, \JSON_THROW_ON_ERROR, 508); + yield '}'; + $prefix = ','; + } + yield '],"stringProperty":'; + yield \json_encode($value1->stringProperty, \JSON_THROW_ON_ERROR, 510); + yield '}'; + $prefix = ','; + } + yield ']'; + } catch (\JsonException $e) { + throw new \Symfony\Component\JsonStreamer\Exception\NotEncodableValueException($e->getMessage(), 0, $e); + } +}; diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nested_list.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nested_list.php new file mode 100644 index 0000000000000..c723ed246ec15 --- /dev/null +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nested_list.php @@ -0,0 +1,29 @@ +dummies as $value2) { + yield $prefix; + yield '{"id":'; + yield \json_encode($value2->id, \JSON_THROW_ON_ERROR, 508); + yield ',"name":'; + yield \json_encode($value2->name, \JSON_THROW_ON_ERROR, 508); + yield '}'; + $prefix = ','; + } + yield '],"customProperty":'; + yield \json_encode($value1->customProperty, \JSON_THROW_ON_ERROR, 510); + yield '}'; + $prefix = ','; + } + yield ']'; + } catch (\JsonException $e) { + throw new \Symfony\Component\JsonStreamer\Exception\NotEncodableValueException($e->getMessage(), 0, $e); + } +}; diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_dict.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_dict.php index b466dd89c9871..3be424621871c 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_dict.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_dict.php @@ -5,13 +5,13 @@ if (\is_array($data)) { yield '{'; $prefix = ''; - foreach ($data as $key => $value) { - $key = \substr(\json_encode($key), 1, -1); - yield "{$prefix}\"{$key}\":"; + foreach ($data as $key1 => $value1) { + $key1 = \substr(\json_encode($key1), 1, -1); + yield "{$prefix}\"{$key1}\":"; yield '{"@id":'; - yield \json_encode($value->id, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->id, \JSON_THROW_ON_ERROR, 510); yield ',"name":'; - yield \json_encode($value->name, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->name, \JSON_THROW_ON_ERROR, 510); yield '}'; $prefix = ','; } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_list.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_list.php index f891ae0a649bc..20bfe43025e06 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_list.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/nullable_object_list.php @@ -5,12 +5,12 @@ if (\is_array($data)) { yield '['; $prefix = ''; - foreach ($data as $value) { + foreach ($data as $value1) { yield $prefix; yield '{"@id":'; - yield \json_encode($value->id, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->id, \JSON_THROW_ON_ERROR, 510); yield ',"name":'; - yield \json_encode($value->name, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->name, \JSON_THROW_ON_ERROR, 510); yield '}'; $prefix = ','; } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_dict.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_dict.php index 9959ab8211300..8059928244a1b 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_dict.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_dict.php @@ -4,13 +4,13 @@ try { yield '{'; $prefix = ''; - foreach ($data as $key => $value) { - $key = \substr(\json_encode($key), 1, -1); - yield "{$prefix}\"{$key}\":"; + foreach ($data as $key1 => $value1) { + $key1 = \substr(\json_encode($key1), 1, -1); + yield "{$prefix}\"{$key1}\":"; yield '{"@id":'; - yield \json_encode($value->id, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->id, \JSON_THROW_ON_ERROR, 510); yield ',"name":'; - yield \json_encode($value->name, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->name, \JSON_THROW_ON_ERROR, 510); yield '}'; $prefix = ','; } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_iterable.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_iterable.php index 5eff34f5e59b8..732e56b889785 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_iterable.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_iterable.php @@ -4,13 +4,13 @@ try { yield '{'; $prefix = ''; - foreach ($data as $key => $value) { - $key = is_int($key) ? $key : \substr(\json_encode($key), 1, -1); - yield "{$prefix}\"{$key}\":"; + foreach ($data as $key1 => $value1) { + $key1 = is_int($key1) ? $key1 : \substr(\json_encode($key1), 1, -1); + yield "{$prefix}\"{$key1}\":"; yield '{"id":'; - yield \json_encode($value->id, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->id, \JSON_THROW_ON_ERROR, 510); yield ',"name":'; - yield \json_encode($value->name, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->name, \JSON_THROW_ON_ERROR, 510); yield '}'; $prefix = ','; } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_list.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_list.php index bb4a6a45d0a46..37ef84a40a19b 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_list.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/object_list.php @@ -4,12 +4,12 @@ try { yield '['; $prefix = ''; - foreach ($data as $value) { + foreach ($data as $value1) { yield $prefix; yield '{"@id":'; - yield \json_encode($value->id, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->id, \JSON_THROW_ON_ERROR, 510); yield ',"name":'; - yield \json_encode($value->name, \JSON_THROW_ON_ERROR, 510); + yield \json_encode($value1->name, \JSON_THROW_ON_ERROR, 510); yield '}'; $prefix = ','; } diff --git a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/union.php b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/union.php index edb5e5c46fe7c..6e2c0566f50d2 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/union.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Fixtures/stream_writer/union.php @@ -5,9 +5,9 @@ if (\is_array($data)) { yield '['; $prefix = ''; - foreach ($data as $value) { + foreach ($data as $value1) { yield $prefix; - yield \json_encode($value->value, \JSON_THROW_ON_ERROR, 511); + yield \json_encode($value1->value, \JSON_THROW_ON_ERROR, 511); $prefix = ','; } yield ']'; diff --git a/src/Symfony/Component/JsonStreamer/Tests/JsonStreamWriterTest.php b/src/Symfony/Component/JsonStreamer/Tests/JsonStreamWriterTest.php index 14cc50881d0d1..88efd38797ea3 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/JsonStreamWriterTest.php +++ b/src/Symfony/Component/JsonStreamer/Tests/JsonStreamWriterTest.php @@ -16,9 +16,11 @@ use Symfony\Component\JsonStreamer\JsonStreamWriter; use Symfony\Component\JsonStreamer\Tests\Fixtures\Enum\DummyBackedEnum; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\ClassicDummy; +use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithArray; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithDateTimes; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithGenerics; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNameAttributes; +use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNestedArray; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNullableProperties; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithPhpDoc; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithUnionProperties; @@ -107,6 +109,34 @@ public function testWriteCollection() new \ArrayObject([new ClassicDummy(), new ClassicDummy()]), Type::iterable(Type::object(ClassicDummy::class), Type::int()), ); + + $dummyWithArray1 = new DummyWithArray(); + $dummyWithArray1->dummies = [new ClassicDummy()]; + $dummyWithArray1->customProperty = 'customProperty1'; + + $dummyWithArray2 = new DummyWithArray(); + $dummyWithArray2->dummies = [new ClassicDummy()]; + $dummyWithArray2->customProperty = 'customProperty2'; + + $this->assertWritten( + '[{"dummies":[{"id":1,"name":"dummy"}],"customProperty":"customProperty1"},{"dummies":[{"id":1,"name":"dummy"}],"customProperty":"customProperty2"}]', + [$dummyWithArray1, $dummyWithArray2], + Type::list(Type::object(DummyWithArray::class)), + ); + + $dummyWithNestedArray1 = new DummyWithNestedArray(); + $dummyWithNestedArray1->dummies = [$dummyWithArray1]; + $dummyWithNestedArray1->stringProperty = 'stringProperty1'; + + $dummyWithNestedArray2 = new DummyWithNestedArray(); + $dummyWithNestedArray2->dummies = [$dummyWithArray2]; + $dummyWithNestedArray2->stringProperty = 'stringProperty2'; + + $this->assertWritten( + '[{"dummies":[{"dummies":[{"id":1,"name":"dummy"}],"customProperty":"customProperty1"}],"stringProperty":"stringProperty1"},{"dummies":[{"dummies":[{"id":1,"name":"dummy"}],"customProperty":"customProperty2"}],"stringProperty":"stringProperty2"}]', + [$dummyWithNestedArray1, $dummyWithNestedArray2], + Type::list(Type::object(DummyWithNestedArray::class)), + ); } public function testWriteObject() diff --git a/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php b/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php index 8ddbef67d9a65..6f1024303a358 100644 --- a/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php +++ b/src/Symfony/Component/JsonStreamer/Tests/Write/StreamWriterGeneratorTest.php @@ -21,7 +21,9 @@ use Symfony\Component\JsonStreamer\Tests\Fixtures\Enum\DummyBackedEnum; use Symfony\Component\JsonStreamer\Tests\Fixtures\Enum\DummyEnum; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\ClassicDummy; +use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithArray; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNameAttributes; +use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNestedArray; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithOtherDummies; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithUnionProperties; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithValueTransformerAttributes; @@ -93,6 +95,8 @@ public static function generatedStreamWriterDataProvider(): iterable yield ['null_list', Type::list(Type::null())]; yield ['object_list', Type::list(Type::object(DummyWithNameAttributes::class))]; yield ['nullable_object_list', Type::nullable(Type::list(Type::object(DummyWithNameAttributes::class)))]; + yield ['nested_list', Type::list(Type::object(DummyWithArray::class))]; + yield ['double_nested_list', Type::list(Type::object(DummyWithNestedArray::class))]; yield ['dict', Type::dict()]; yield ['object_dict', Type::dict(Type::object(DummyWithNameAttributes::class))]; @@ -141,6 +145,7 @@ public function testCallPropertyMetadataLoaderWithProperContext() ->with(self::class, [], [ 'original_type' => $type, 'generated_classes' => [self::class => true], + 'depth' => 0, ]) ->willReturn([]); diff --git a/src/Symfony/Component/JsonStreamer/Write/PhpAstBuilder.php b/src/Symfony/Component/JsonStreamer/Write/PhpAstBuilder.php index f0b429b42c8f3..d33ba3a9a508e 100644 --- a/src/Symfony/Component/JsonStreamer/Write/PhpAstBuilder.php +++ b/src/Symfony/Component/JsonStreamer/Write/PhpAstBuilder.php @@ -309,21 +309,23 @@ private function buildYieldStatements(DataModelNodeInterface $dataModelNode, arr ]; } + $keyVar = $dataModelNode->getKeyNode()->getAccessor()->toPhpExpr(); + $escapedKey = $dataModelNode->getType()->getCollectionKeyType()->isIdentifiedBy(TypeIdentifier::INT) - ? new Ternary($this->builder->funcCall('is_int', [$this->builder->var('key')]), $this->builder->var('key'), $this->escapeString($this->builder->var('key'))) - : $this->escapeString($this->builder->var('key')); + ? new Ternary($this->builder->funcCall('is_int', [$keyVar]), $keyVar, $this->escapeString($keyVar)) + : $this->escapeString($keyVar); return [ new Expression(new Yield_($this->builder->val('{'))), new Expression(new Assign($this->builder->var('prefix'), $this->builder->val(''))), new Foreach_($accessor, $dataModelNode->getItemNode()->getAccessor()->toPhpExpr(), [ - 'keyVar' => $this->builder->var('key'), + 'keyVar' => $keyVar, 'stmts' => [ - new Expression(new Assign($this->builder->var('key'), $escapedKey)), + new Expression(new Assign($keyVar, $escapedKey)), new Expression(new Yield_(new Encapsed([ $this->builder->var('prefix'), new EncapsedStringPart('"'), - $this->builder->var('key'), + $keyVar, new EncapsedStringPart('":'), ]))), ...$this->buildYieldStatements($dataModelNode->getItemNode(), $options, $context), diff --git a/src/Symfony/Component/JsonStreamer/Write/StreamWriterGenerator.php b/src/Symfony/Component/JsonStreamer/Write/StreamWriterGenerator.php index c437ca0d179f5..f7ac60f21deee 100644 --- a/src/Symfony/Component/JsonStreamer/Write/StreamWriterGenerator.php +++ b/src/Symfony/Component/JsonStreamer/Write/StreamWriterGenerator.php @@ -76,7 +76,7 @@ public function generate(Type $type, array $options = []): string $this->phpPrinter ??= new Standard(['phpVersion' => PhpVersion::fromComponents(8, 2)]); $this->fs ??= new Filesystem(); - $dataModel = $this->createDataModel($type, new VariableDataAccessor('data'), $options); + $dataModel = $this->createDataModel($type, new VariableDataAccessor('data'), $options, ['depth' => 0]); $nodes = $this->phpAstBuilder->build($dataModel, $options); $nodes = $this->phpOptimizer->optimize($nodes); @@ -180,10 +180,13 @@ private function createDataModel(Type $type, DataAccessorInterface $accessor, ar } if ($type instanceof CollectionType) { + ++$context['depth']; + return new CollectionNode( $accessor, $type, - $this->createDataModel($type->getCollectionValueType(), new VariableDataAccessor('value'), $options, $context), + $this->createDataModel($type->getCollectionValueType(), new VariableDataAccessor('value'.$context['depth']), $options, $context), + $this->createDataModel($type->getCollectionKeyType(), new VariableDataAccessor('key'.$context['depth']), $options, $context), ); } diff --git a/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php b/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php index cf390a046040c..79c9362d5e03f 100644 --- a/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php +++ b/src/Symfony/Component/Lock/Store/DoctrineDbalStore.php @@ -251,12 +251,12 @@ private function getCurrentTimestampStatement(): string } return match (true) { - $platform instanceof \Doctrine\DBAL\Platforms\AbstractMySQLPlatform => 'UNIX_TIMESTAMP()', - $platform instanceof $sqlitePlatformClass => 'strftime(\'%s\',\'now\')', - $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform => 'CAST(EXTRACT(epoch FROM NOW()) AS INT)', - $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => '(SYSDATE - TO_DATE(\'19700101\',\'yyyymmdd\'))*86400 - TO_NUMBER(SUBSTR(TZ_OFFSET(sessiontimezone), 1, 3))*3600', - $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform => 'DATEDIFF(s, \'1970-01-01\', GETUTCDATE())', - default => (string) time(), + $platform instanceof \Doctrine\DBAL\Platforms\AbstractMySQLPlatform => 'UNIX_TIMESTAMP(NOW(6))', + $platform instanceof $sqlitePlatformClass => "(julianday('now') - 2440587.5) * 86400.0", + $platform instanceof \Doctrine\DBAL\Platforms\PostgreSQLPlatform => 'CAST(EXTRACT(epoch FROM NOW()) AS DOUBLE PRECISION)', + $platform instanceof \Doctrine\DBAL\Platforms\OraclePlatform => "(CAST(systimestamp AT TIME ZONE 'UTC' AS DATE) - DATE '1970-01-01') * 86400 + TO_NUMBER(TO_CHAR(systimestamp AT TIME ZONE 'UTC', 'SSSSS.FF'))", + $platform instanceof \Doctrine\DBAL\Platforms\SQLServerPlatform => "CAST(DATEDIFF_BIG(ms, '1970-01-01', SYSUTCDATETIME()) AS FLOAT) / 1000.0", + default => (new \DateTimeImmutable())->format('U.u'), }; } diff --git a/src/Symfony/Component/Lock/Store/MongoDbStore.php b/src/Symfony/Component/Lock/Store/MongoDbStore.php index e9ce69a0ecd8b..d015ea5fa269b 100644 --- a/src/Symfony/Component/Lock/Store/MongoDbStore.php +++ b/src/Symfony/Component/Lock/Store/MongoDbStore.php @@ -20,6 +20,8 @@ use MongoDB\Driver\Exception\BulkWriteException; use MongoDB\Driver\Manager; use MongoDB\Driver\Query; +use MongoDB\Driver\ReadPreference; +use MongoDB\Driver\WriteConcern; use MongoDB\Exception\DriverRuntimeException; use MongoDB\Exception\InvalidArgumentException as MongoInvalidArgumentException; use MongoDB\Exception\UnsupportedException; @@ -60,9 +62,9 @@ class MongoDbStore implements PersistingStoreInterface private array $options; /** - * @param Collection|Client|Manager|string $mongo An instance of a Collection or Client or URI @see https://docs.mongodb.com/manual/reference/connection-string/ - * @param array $options See below - * @param float $initialTtl The expiration delay of locks in seconds + * @param Collection|Database|Client|Manager|string $mongo An instance of a Collection or Client or URI @see https://docs.mongodb.com/manual/reference/connection-string/ + * @param array $options See below + * @param float $initialTtl The expiration delay of locks in seconds * * @throws InvalidArgumentException If required options are not provided * @throws InvalidTtlException When the initial ttl is not valid @@ -88,8 +90,10 @@ class MongoDbStore implements PersistingStoreInterface * to 0.0 and optionally leverage * self::createTtlIndex(int $expireAfterSeconds = 0). * - * writeConcern and readConcern are not specified by MongoDbStore meaning the connection's settings will take effect. - * readPreference is primary for all queries. + * readConcern is not specified by MongoDbStore meaning the connection's settings will take effect. + * writeConcern is majority for all update queries. + * readPreference is primary for all read queries. + * * @see https://docs.mongodb.com/manual/applications/replication/ */ public function __construct( @@ -142,7 +146,7 @@ public function __construct( * * Non-standard parameters are removed from the URI to improve libmongoc's re-use of connections. * - * @see https://www.php.net/manual/en/mongodb.connection-handling.php + * @see https://php.net/mongodb.connection-handling */ private function skimUri(string $uri): string { @@ -270,7 +274,11 @@ public function delete(Key $key): void ['limit' => 1] ); - $this->getManager()->executeBulkWrite($this->namespace, $write); + $this->getManager()->executeBulkWrite( + $this->namespace, + $write, + ['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)] + ); } public function exists(Key $key): bool @@ -287,7 +295,9 @@ public function exists(Key $key): bool 'limit' => 1, 'projection' => ['_id' => 1], ] - )); + ), [ + 'readPreference' => new ReadPreference(ReadPreference::PRIMARY) + ]); return [] !== $cursor->toArray(); } @@ -329,7 +339,11 @@ private function upsert(Key $key, float $ttl): void ] ); - $this->getManager()->executeBulkWrite($this->namespace, $write); + $this->getManager()->executeBulkWrite( + $this->namespace, + $write, + ['writeConcern' => new WriteConcern(WriteConcern::MAJORITY)] + ); } private function isDuplicateKeyException(BulkWriteException $e): bool diff --git a/src/Symfony/Component/Lock/Store/PdoStore.php b/src/Symfony/Component/Lock/Store/PdoStore.php index 1b64cdd5cef48..96b30291585b1 100644 --- a/src/Symfony/Component/Lock/Store/PdoStore.php +++ b/src/Symfony/Component/Lock/Store/PdoStore.php @@ -220,12 +220,12 @@ private function getDriver(): string private function getCurrentTimestampStatement(): string { return match ($this->getDriver()) { - 'mysql' => 'UNIX_TIMESTAMP()', - 'sqlite' => 'strftime(\'%s\',\'now\')', - 'pgsql' => 'CAST(EXTRACT(epoch FROM NOW()) AS INT)', - 'oci' => '(SYSDATE - TO_DATE(\'19700101\',\'yyyymmdd\'))*86400 - TO_NUMBER(SUBSTR(TZ_OFFSET(sessiontimezone), 1, 3))*3600', - 'sqlsrv' => 'DATEDIFF(s, \'1970-01-01\', GETUTCDATE())', - default => (string) time(), + 'mysql' => 'UNIX_TIMESTAMP(NOW(6))', + 'sqlite' => "(julianday('now') - 2440587.5) * 86400.0", + 'pgsql' => 'CAST(EXTRACT(epoch FROM NOW()) AS DOUBLE PRECISION)', + 'oci' => "(CAST(systimestamp AT TIME ZONE 'UTC' AS DATE) - DATE '1970-01-01') * 86400 + TO_NUMBER(TO_CHAR(systimestamp AT TIME ZONE 'UTC', 'SSSSS.FF'))", + 'sqlsrv' => "CAST(DATEDIFF_BIG(ms, '1970-01-01', SYSUTCDATETIME()) AS FLOAT) / 1000.0", + default => (new \DateTimeImmutable())->format('U.u'), }; } diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index e23856f79a5d8..3356fc32670f3 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -295,7 +295,13 @@ private function evaluate(string $script, string $resource, array $args): mixed } } - $this->handlePredisError(fn () => $this->redis->script('LOAD', $script)); + if ($this->redis->getConnection() instanceof \Predis\Connection\Cluster\ClusterInterface) { + foreach ($this->redis as $connection) { + $this->handlePredisError(fn () => $connection->script('LOAD', $script)); + } + } else { + $this->handlePredisError(fn () => $this->redis->script('LOAD', $script)); + } return $this->handlePredisError(fn () => $this->redis->evalSha($scriptSha, 1, $resource, ...$args)); } diff --git a/src/Symfony/Component/Mailer/Bridge/Brevo/Webhook/BrevoRequestParser.php b/src/Symfony/Component/Mailer/Bridge/Brevo/Webhook/BrevoRequestParser.php index ea6759b39c5e8..464a0219cd923 100644 --- a/src/Symfony/Component/Mailer/Bridge/Brevo/Webhook/BrevoRequestParser.php +++ b/src/Symfony/Component/Mailer/Bridge/Brevo/Webhook/BrevoRequestParser.php @@ -35,9 +35,9 @@ protected function getRequestMatcher(): RequestMatcherInterface return new ChainRequestMatcher([ new MethodRequestMatcher('POST'), new IsJsonRequestMatcher(), - // https://developers.brevo.com/docs/how-to-use-webhooks#securing-your-webhooks + // https://help.brevo.com/hc/en-us/articles/15127404548498-Brevo-IP-ranges-List-of-publicly-exposed-services // localhost is added for testing - new IpsRequestMatcher(['185.107.232.1/24', '1.179.112.1/20', '127.0.0.1']), + new IpsRequestMatcher(['1.179.112.0/20', '172.246.240.0/20', '127.0.0.1']), ]); } diff --git a/src/Symfony/Component/Mailer/Tests/EventListener/MessengerTransportListenerTest.php b/src/Symfony/Component/Mailer/Tests/EventListener/MessengerTransportListenerTest.php index 0a44c109e331f..e9ee7423c6ac8 100644 --- a/src/Symfony/Component/Mailer/Tests/EventListener/MessengerTransportListenerTest.php +++ b/src/Symfony/Component/Mailer/Tests/EventListener/MessengerTransportListenerTest.php @@ -41,7 +41,7 @@ public function testMessengerTransportStampViaHeader() $event = new MessageEvent($message, $envelope, 'smtp', true); $l->onMessage($event); $this->assertCount(1, $event->getStamps()); - /* @var TransportNamesStamp $stamp */ + /** @var TransportNamesStamp $stamp */ $this->assertInstanceOf(TransportNamesStamp::class, $stamp = $event->getStamps()[0]); $this->assertSame(['async'], $stamp->getTransportNames()); $this->assertFalse($message->getHeaders()->has('X-Bus-Transport')); @@ -57,7 +57,7 @@ public function testMessengerTransportStampsViaHeader() $event = new MessageEvent($message, $envelope, 'smtp', true); $l->onMessage($event); $this->assertCount(1, $event->getStamps()); - /* @var TransportNamesStamp $stamp */ + /** @var TransportNamesStamp $stamp */ $this->assertInstanceOf(TransportNamesStamp::class, $stamp = $event->getStamps()[0]); $this->assertSame(['async', 'async1', $name], $stamp->getTransportNames()); $this->assertFalse($message->getHeaders()->has('X-Bus-Transport')); diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php index 5d7c0b0a8fb97..d7592d0fc55d2 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php @@ -144,7 +144,7 @@ public function testRetryAndDelay() // this should be the custom routing key message first $this->assertCount(1, $envelopes); - /* @var Envelope $envelope */ + /** @var Envelope $envelope */ $receiver->ack($envelopes[0]); $this->assertEquals($customRoutingKeyMessage, $envelopes[0]->getMessage()); @@ -153,7 +153,7 @@ public function testRetryAndDelay() // duration should be about 2 seconds $this->assertApproximateDuration($startTime, 2); - /* @var RedeliveryStamp|null $retryStamp */ + /** @var RedeliveryStamp|null $retryStamp */ // verify the stamp still exists from the last send $this->assertCount(1, $envelopes); $retryStamp = $envelopes[0]->last(RedeliveryStamp::class); diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php index 6ed21386b6434..6306cbc62da9d 100644 --- a/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php +++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/Connection.php @@ -26,6 +26,9 @@ use Doctrine\DBAL\Schema\Name\Identifier; use Doctrine\DBAL\Schema\Name\UnqualifiedName; use Doctrine\DBAL\Schema\PrimaryKeyConstraint; +use Doctrine\DBAL\Schema\AbstractSchemaManager; +use Doctrine\DBAL\Schema\Comparator; +use Doctrine\DBAL\Schema\ComparatorConfig; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Types; @@ -577,8 +580,14 @@ private function decodeEnvelopeHeaders(array $doctrineEnvelope): array private function updateSchema(): void { $schemaManager = $this->driverConnection->createSchemaManager(); - $schemaDiff = $schemaManager->createComparator() - ->compareSchemas($schemaManager->introspectSchema(), $this->getSchema()); + + if (class_exists(ComparatorConfig::class)) { + $comparator = $schemaManager->createComparator((new ComparatorConfig())->withReportModifiedIndexes(false)); + } else { + $comparator = $schemaManager->createComparator(); + } + + $schemaDiff = $comparator->compareSchemas($schemaManager->introspectSchema(), $this->getSchema()); $platform = $this->driverConnection->getDatabasePlatform(); if ($platform->supportsSchemas()) { diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php index e86765cca1407..e7fdb75c8427e 100644 --- a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php +++ b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php @@ -146,7 +146,7 @@ private function getMessageIdsByClassFilter(string $classFilter, ListableReceive } $ids[] = $this->getMessageId($envelope); - }; + } } finally { $this->phpSerializer?->rejectPhpIncompleteClass(); } diff --git a/src/Symfony/Component/Messenger/Middleware/RouterContextMiddleware.php b/src/Symfony/Component/Messenger/Middleware/RouterContextMiddleware.php index 9a234df090bb1..cf5105bf475e6 100644 --- a/src/Symfony/Component/Messenger/Middleware/RouterContextMiddleware.php +++ b/src/Symfony/Component/Messenger/Middleware/RouterContextMiddleware.php @@ -56,7 +56,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope $currentPathInfo = $context->getPathInfo(); $currentQueryString = $context->getQueryString(); - /* @var RouterContextStamp $contextStamp */ + /** @var RouterContextStamp $contextStamp */ $context ->setBaseUrl($contextStamp->getBaseUrl()) ->setMethod($contextStamp->getMethod()) diff --git a/src/Symfony/Component/Messenger/Tests/Command/ConsumeMessagesCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/ConsumeMessagesCommandTest.php index 7183f2e7c67d7..e6ec50cc6c1c4 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/ConsumeMessagesCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/ConsumeMessagesCommandTest.php @@ -222,7 +222,7 @@ public function testRunWithMemoryLimit() $busLocator = new Container(); $busLocator->set('dummy-bus', $bus); - $logger = new class() implements LoggerInterface { + $logger = new class implements LoggerInterface { use LoggerTrait; public array $logs = []; diff --git a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php index ee83c39fb0d59..21df1d6b8c912 100644 --- a/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php +++ b/src/Symfony/Component/Messenger/Tests/Command/FailedMessagesRemoveCommandTest.php @@ -221,7 +221,7 @@ public function testRemoveMessagesFilteredByClassMessage() ); $tester = new CommandTester($command); - $tester->execute(['--class-filter' => "stdClass", '--force' => true, '--show-messages' => true]); + $tester->execute(['--class-filter' => 'stdClass', '--force' => true, '--show-messages' => true]); $this->assertStringContainsString('Can you confirm you want to remove 2 messages? (yes/no)', $tester->getDisplay()); $this->assertStringContainsString('Failed Message Details', $tester->getDisplay()); diff --git a/src/Symfony/Component/Messenger/Tests/EventListener/SendFailedMessageToFailureTransportListenerTest.php b/src/Symfony/Component/Messenger/Tests/EventListener/SendFailedMessageToFailureTransportListenerTest.php index 9060ff515ed84..a6473e6c1a8a1 100644 --- a/src/Symfony/Component/Messenger/Tests/EventListener/SendFailedMessageToFailureTransportListenerTest.php +++ b/src/Symfony/Component/Messenger/Tests/EventListener/SendFailedMessageToFailureTransportListenerTest.php @@ -26,7 +26,7 @@ public function testItSendsToTheFailureTransportWithSenderLocator() $receiverName = 'my_receiver'; $sender = $this->createMock(SenderInterface::class); $sender->expects($this->once())->method('send')->with($this->callback(function ($envelope) use ($receiverName) { - /* @var Envelope $envelope */ + /** @var Envelope $envelope */ $this->assertInstanceOf(Envelope::class, $envelope); /** @var SentToFailureTransportStamp $sentToFailureTransportStamp */ @@ -101,7 +101,7 @@ public function testItSendsToTheFailureTransportWithMultipleFailedTransports() $receiverName = 'my_receiver'; $sender = $this->createMock(SenderInterface::class); $sender->expects($this->once())->method('send')->with($this->callback(function ($envelope) use ($receiverName) { - /* @var Envelope $envelope */ + /** @var Envelope $envelope */ $this->assertInstanceOf(Envelope::class, $envelope); /** @var SentToFailureTransportStamp $sentToFailureTransportStamp */ diff --git a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php index 762e591044e8e..eb8af4cd2ca23 100644 --- a/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php +++ b/src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php @@ -41,7 +41,7 @@ public function testItSendsTheMessageToAssignedSender() $envelope = $middleware->handle($envelope, $this->getStackMock(false)); - /* @var SentStamp $stamp */ + /** @var SentStamp $stamp */ $this->assertInstanceOf(SentStamp::class, $stamp = $envelope->last(SentStamp::class), 'it adds a sent stamp'); $this->assertSame('my_sender', $stamp->getSenderAlias()); $this->assertSame($sender::class, $stamp->getSenderClass()); diff --git a/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php b/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php index e38909f7c7f94..d7c0af68b8a5f 100644 --- a/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php +++ b/src/Symfony/Component/Mime/Crypto/SMimeEncrypter.php @@ -24,7 +24,7 @@ final class SMimeEncrypter extends SMime /** * @param string|string[] $certificate The path (or array of paths) of the file(s) containing the X.509 certificate(s) - * @param int|null $cipher A set of algorithms used to encrypt the message. Must be one of these PHP constants: https://www.php.net/manual/en/openssl.ciphers.php + * @param int|null $cipher A set of algorithms used to encrypt the message. Must be one of these PHP constants: https://php.net/openssl.ciphers */ public function __construct(string|array $certificate, ?int $cipher = null) { diff --git a/src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php b/src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php index 733023eb38766..16622cc89f18f 100644 --- a/src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php +++ b/src/Symfony/Component/Mime/FileinfoMimeTypeGuesser.php @@ -30,7 +30,7 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface /** * @param string|null $magicFile A magic file to use with the finfo instance * - * @see http://www.php.net/manual/en/function.finfo-open.php + * @see https://php.net/finfo-open */ public function __construct( private ?string $magicFile = null, diff --git a/src/Symfony/Component/Mime/Tests/EmailTest.php b/src/Symfony/Component/Mime/Tests/EmailTest.php index 3aa86c5f94623..480c9b3e6fd3a 100644 --- a/src/Symfony/Component/Mime/Tests/EmailTest.php +++ b/src/Symfony/Component/Mime/Tests/EmailTest.php @@ -477,7 +477,7 @@ private function generateSomeParts(): array public function testAttachments() { // inline part - $contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test', 'r'); + $contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test'); $att = new DataPart($file = fopen($name, 'r'), 'test'); $inline = (new DataPart($contents, 'test'))->asInline(); $e = new Email(); @@ -618,7 +618,7 @@ public function testHtmlBodyAcceptedTypes() $email->html(null); $this->assertNull($email->getHtmlBody()); - $contents = file_get_contents(__DIR__.'/Fixtures/mimetypes/test', 'r'); + $contents = file_get_contents(__DIR__.'/Fixtures/mimetypes/test'); $email->html($contents); $this->assertSame($contents, $email->getHtmlBody()); } @@ -641,7 +641,7 @@ public function testTextBodyAcceptedTypes() $email->text(null); $this->assertNull($email->getTextBody()); - $contents = file_get_contents(__DIR__.'/Fixtures/mimetypes/test', 'r'); + $contents = file_get_contents(__DIR__.'/Fixtures/mimetypes/test'); $email->text($contents); $this->assertSame($contents, $email->getTextBody()); } diff --git a/src/Symfony/Component/ObjectMapper/Attribute/Map.php b/src/Symfony/Component/ObjectMapper/Attribute/Map.php index 143842221d496..0dc7ddd60b4a5 100644 --- a/src/Symfony/Component/ObjectMapper/Attribute/Map.php +++ b/src/Symfony/Component/ObjectMapper/Attribute/Map.php @@ -22,8 +22,8 @@ class Map { /** - * @param string|class-string|null $source The property or the class to map from - * @param string|class-string|null $target The property or the class to map to + * @param string|class-string|null $source The property or the class to map from + * @param string|class-string|null $target The property or the class to map to * @param string|bool|callable(mixed, object): bool|null $if A boolean, a service id or a callable that instructs whether to map * @param (string|callable(mixed, object): mixed)|(string|callable(mixed, object): mixed)[]|null $transform A service id or a callable that transforms the value during mapping */ diff --git a/src/Symfony/Component/ObjectMapper/ConditionCallableInterface.php b/src/Symfony/Component/ObjectMapper/ConditionCallableInterface.php index 05084591e1fbd..12d3ade1c4235 100644 --- a/src/Symfony/Component/ObjectMapper/ConditionCallableInterface.php +++ b/src/Symfony/Component/ObjectMapper/ConditionCallableInterface.php @@ -24,8 +24,8 @@ interface ConditionCallableInterface { /** - * @param mixed $value The value being mapped - * @param T $source The object we're working on + * @param mixed $value The value being mapped + * @param T $source The object we're working on * @param T2|null $target The target we're mapping to */ public function __invoke(mixed $value, object $source, ?object $target): bool; diff --git a/src/Symfony/Component/ObjectMapper/Exception/NoSuchPropertyException.php b/src/Symfony/Component/ObjectMapper/Exception/NoSuchPropertyException.php new file mode 100644 index 0000000000000..3b5df303dcc1f --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Exception/NoSuchPropertyException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Exception; + +/** + * Thrown when a property cannot be found. + * + * @author Antoine Bluchet + */ +class NoSuchPropertyException extends MappingException +{ +} diff --git a/src/Symfony/Component/ObjectMapper/ObjectMapper.php b/src/Symfony/Component/ObjectMapper/ObjectMapper.php index 69f02fb7f1160..64840948aa45d 100644 --- a/src/Symfony/Component/ObjectMapper/ObjectMapper.php +++ b/src/Symfony/Component/ObjectMapper/ObjectMapper.php @@ -14,10 +14,13 @@ use Psr\Container\ContainerInterface; use Symfony\Component\ObjectMapper\Exception\MappingException; use Symfony\Component\ObjectMapper\Exception\MappingTransformException; +use Symfony\Component\ObjectMapper\Exception\NoSuchPropertyException; use Symfony\Component\ObjectMapper\Metadata\Mapping; use Symfony\Component\ObjectMapper\Metadata\ObjectMapperMetadataFactoryInterface; use Symfony\Component\ObjectMapper\Metadata\ReflectionObjectMapperMetadataFactory; +use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException as PropertyAccessorNoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; +use Symfony\Component\VarExporter\LazyObjectInterface; /** * Object to object mapper. @@ -141,12 +144,17 @@ public function map(object $source, object|string|null $target = null): object } if (!$mappings && $targetRefl->hasProperty($propertyName)) { + $sourceProperty = $refl->getProperty($propertyName); + if ($refl->isInstance($source) && !$sourceProperty->isInitialized($source)) { + continue; + } + $value = $this->getSourceValue($source, $mappedTarget, $this->getRawValue($source, $propertyName), $this->objectMap); $this->storeValue($propertyName, $mapToProperties, $ctorArguments, $value); } } - if (!$mappingToObject && $ctorArguments && $constructor) { + if (!$mappingToObject && !$map?->transform && $constructor) { try { $mappedTarget->__construct(...$ctorArguments); } catch (\ReflectionException $e) { @@ -154,6 +162,14 @@ public function map(object $source, object|string|null $target = null): object } } + if ($mappingToObject && $ctorArguments) { + foreach ($ctorArguments as $property => $value) { + if ($targetRefl->hasProperty($property) && $targetRefl->getProperty($property)->isPublic()) { + $mapToProperties[$property] = $value; + } + } + } + foreach ($mapToProperties as $property => $value) { $this->propertyAccessor ? $this->propertyAccessor->setValue($mappedTarget, $property, $value) : ($mappedTarget->{$property} = $value); } @@ -167,7 +183,19 @@ public function map(object $source, object|string|null $target = null): object private function getRawValue(object $source, string $propertyName): mixed { - return $this->propertyAccessor ? $this->propertyAccessor->getValue($source, $propertyName) : $source->{$propertyName}; + if ($this->propertyAccessor) { + try { + return $this->propertyAccessor->getValue($source, $propertyName); + } catch (PropertyAccessorNoSuchPropertyException $e) { + throw new NoSuchPropertyException($e->getMessage(), $e->getCode(), $e); + } + } + + if (!property_exists($source, $propertyName) && !isset($source->{$propertyName})) { + throw new NoSuchPropertyException(\sprintf('The property "%s" does not exist on "%s".', $propertyName, get_debug_type($source))); + } + + return $source->{$propertyName}; } private function getSourceValue(object $source, object $target, mixed $value, \SplObjectStorage $objectMap, ?Mapping $mapping = null): mixed @@ -293,6 +321,12 @@ private function getSourceReflectionClass(object $source, \ReflectionClass $targ throw new MappingException($e->getMessage(), $e->getCode(), $e); } + if ($source instanceof LazyObjectInterface) { + $source->initializeLazyObject(); + } elseif (\PHP_VERSION_ID >= 80400 && $refl->isUninitializedLazyObject($source)) { + $refl->initializeLazyObject($source); + } + if ($metadata) { return $refl; } diff --git a/src/Symfony/Component/ObjectMapper/ObjectMapperInterface.php b/src/Symfony/Component/ObjectMapper/ObjectMapperInterface.php index 0df5a0fbfddbd..9eb3bc5d5af0b 100644 --- a/src/Symfony/Component/ObjectMapper/ObjectMapperInterface.php +++ b/src/Symfony/Component/ObjectMapper/ObjectMapperInterface.php @@ -13,6 +13,7 @@ use Symfony\Component\ObjectMapper\Exception\MappingException; use Symfony\Component\ObjectMapper\Exception\MappingTransformException; +use Symfony\Component\ObjectMapper\Exception\NoSuchPropertyException; /** * Object to object mapper. @@ -33,6 +34,7 @@ interface ObjectMapperInterface * * @throws MappingException When the mapping configuration is wrong * @throws MappingTransformException When a transformation on an object does not return an object + * @throws NoSuchPropertyException When a property does not exist */ public function map(object $source, object|string|null $target = null): object; } diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/DefaultValueStdClass/TargetDto.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/DefaultValueStdClass/TargetDto.php new file mode 100644 index 0000000000000..e595c103a4e35 --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/DefaultValueStdClass/TargetDto.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\InitializedConstructor; + +class A +{ + public array $tags = ['foo', 'bar']; +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InitializedConstructor/B.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InitializedConstructor/B.php new file mode 100644 index 0000000000000..007418edc2b23 --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/InitializedConstructor/B.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\InitializedConstructor; + +class B +{ + public array $tags; + + public function __construct() + { + $this->tags = []; + } + + public function addTag($tag) + { + $this->tags[] = $tag; + } + + public function removeTag($tag) + { + } +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/LazyFoo.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/LazyFoo.php new file mode 100644 index 0000000000000..22dbebaad14aa --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/LazyFoo.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures; + +use Symfony\Component\VarExporter\LazyObjectInterface; + +class LazyFoo extends \stdClass implements LazyObjectInterface +{ + private bool $initialized = false; + + public function isLazyObjectInitialized(bool $partial = false): bool + { + return $this->initialized; + } + + public function initializeLazyObject(): object + { + $this->initialized = true; + + return $this; + } + + public function resetLazyObject(): bool + { + $this->initialized = false; + + return true; + } +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/MyProxy.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/MyProxy.php new file mode 100644 index 0000000000000..50d64a80ff4bc --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/MyProxy.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures; + +class MyProxy +{ + public string $name; +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PartialInput/FinalInput.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PartialInput/FinalInput.php new file mode 100644 index 0000000000000..2aeab4c5bcab1 --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PartialInput/FinalInput.php @@ -0,0 +1,11 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\PromotedConstructor; + +class Source +{ + public function __construct( + public int $id, + public string $name, + ) { + } +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PromotedConstructor/Target.php b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PromotedConstructor/Target.php new file mode 100644 index 0000000000000..5833e1d08ca20 --- /dev/null +++ b/src/Symfony/Component/ObjectMapper/Tests/Fixtures/PromotedConstructor/Target.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ObjectMapper\Tests\Fixtures\PromotedConstructor; + +class Target +{ + public function __construct( + public int $id, + public string $name, + ) { + } +} diff --git a/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php b/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php index 99153c3fbdfc7..85b09d1ad99c0 100644 --- a/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php +++ b/src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php @@ -15,10 +15,12 @@ use Psr\Container\ContainerInterface; use Symfony\Component\ObjectMapper\Exception\MappingException; use Symfony\Component\ObjectMapper\Exception\MappingTransformException; +use Symfony\Component\ObjectMapper\Exception\NoSuchPropertyException; use Symfony\Component\ObjectMapper\Metadata\Mapping; use Symfony\Component\ObjectMapper\Metadata\ObjectMapperMetadataFactoryInterface; use Symfony\Component\ObjectMapper\Metadata\ReflectionObjectMapperMetadataFactory; use Symfony\Component\ObjectMapper\ObjectMapper; +use Symfony\Component\ObjectMapper\ObjectMapperInterface; use Symfony\Component\ObjectMapper\Tests\Fixtures\A; use Symfony\Component\ObjectMapper\Tests\Fixtures\B; use Symfony\Component\ObjectMapper\Tests\Fixtures\C; @@ -28,14 +30,18 @@ use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\RecursiveDto; use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\Relation; use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\RelationDto; +use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultValueStdClass\TargetDto; use Symfony\Component\ObjectMapper\Tests\Fixtures\Flatten\TargetUser; use Symfony\Component\ObjectMapper\Tests\Fixtures\Flatten\User; use Symfony\Component\ObjectMapper\Tests\Fixtures\Flatten\UserProfile; use Symfony\Component\ObjectMapper\Tests\Fixtures\HydrateObject\SourceOnly; +use Symfony\Component\ObjectMapper\Tests\Fixtures\InitializedConstructor\A as InitializedConstructorA; +use Symfony\Component\ObjectMapper\Tests\Fixtures\InitializedConstructor\B as InitializedConstructorB; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallback\A as InstanceCallbackA; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallback\B as InstanceCallbackB; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\A as InstanceCallbackWithArgumentsA; use Symfony\Component\ObjectMapper\Tests\Fixtures\InstanceCallbackWithArguments\B as InstanceCallbackWithArgumentsB; +use Symfony\Component\ObjectMapper\Tests\Fixtures\LazyFoo; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\AToBMapper; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\MapStructMapperMetadataFactory; use Symfony\Component\ObjectMapper\Tests\Fixtures\MapStruct\Source; @@ -47,6 +53,11 @@ use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargetProperty\C as MultipleTargetPropertyC; use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargets\A as MultipleTargetsA; use Symfony\Component\ObjectMapper\Tests\Fixtures\MultipleTargets\C as MultipleTargetsC; +use Symfony\Component\ObjectMapper\Tests\Fixtures\MyProxy; +use Symfony\Component\ObjectMapper\Tests\Fixtures\PartialInput\FinalInput; +use Symfony\Component\ObjectMapper\Tests\Fixtures\PartialInput\PartialInput; +use Symfony\Component\ObjectMapper\Tests\Fixtures\PromotedConstructor\Source as PromotedConstructorSource; +use Symfony\Component\ObjectMapper\Tests\Fixtures\PromotedConstructor\Target as PromotedConstructorTarget; use Symfony\Component\ObjectMapper\Tests\Fixtures\Recursion\AB; use Symfony\Component\ObjectMapper\Tests\Fixtures\Recursion\Dto; use Symfony\Component\ObjectMapper\Tests\Fixtures\ServiceLocator\A as ServiceLocatorA; @@ -147,6 +158,15 @@ public function testDeeperRecursion() $this->assertInstanceOf(RelationDto::class, $mapped->relation); } + public function testMapWithInitializedConstructor() + { + $a = new InitializedConstructorA(); + $mapper = new ObjectMapper(propertyAccessor: PropertyAccess::createPropertyAccessor()); + $b = $mapper->map($a, InitializedConstructorB::class); + $this->assertInstanceOf(InitializedConstructorB::class, $b); + $this->assertEquals($b->tags, ['foo', 'bar']); + } + public function testMapToWithInstanceHook() { $a = new InstanceCallbackA(); @@ -236,8 +256,17 @@ public function testSourceOnly() $mapped = $mapper->map($a, SourceOnly::class); $this->assertInstanceOf(SourceOnly::class, $mapped); $this->assertSame('test', $mapped->mappedName); + } + public function testSourceOnlyWithMagicMethods() + { + $mapper = new ObjectMapper(); $a = new class { + public function __isset($key): bool + { + return 'name' === $key; + } + public function __get(string $key): string { return match ($key) { @@ -303,4 +332,119 @@ public function testMultipleTargetMapProperty() $this->assertEquals('donotmap', $c->foo); $this->assertEquals('foo', $c->doesNotExistInTargetB); } + + public function testDefaultValueStdClass() + { + $this->expectException(NoSuchPropertyException::class); + $u = new \stdClass(); + $u->id = 'abc'; + $mapper = new ObjectMapper(); + $b = $mapper->map($u, TargetDto::class); + } + + public function testDefaultValueStdClassWithPropertyInfo() + { + $u = new \stdClass(); + $u->id = 'abc'; + $mapper = new ObjectMapper(propertyAccessor: PropertyAccess::createPropertyAccessorBuilder()->disableExceptionOnInvalidPropertyPath()->getPropertyAccessor()); + $b = $mapper->map($u, TargetDto::class); + $this->assertInstanceOf(TargetDto::class, $b); + $this->assertSame('abc', $b->id); + $this->assertNull($b->optional); + } + + /** + * @dataProvider objectMapperProvider + */ + public function testUpdateObjectWithConstructorPromotedProperties(ObjectMapperInterface $mapper) + { + $a = new PromotedConstructorSource(1, 'foo'); + $b = new PromotedConstructorTarget(1, 'bar'); + $v = $mapper->map($a, $b); + $this->assertSame($v->name, 'foo'); + } + + /** + * @return iterable + */ + public static function objectMapperProvider(): iterable + { + yield [new ObjectMapper()]; + yield [new ObjectMapper(new ReflectionObjectMapperMetadataFactory(), PropertyAccess::createPropertyAccessor())]; + } + + public function testMapInitializesLazyObject() + { + $lazy = new LazyFoo(); + $mapper = new ObjectMapper(); + $mapper->map($lazy, \stdClass::class); + $this->assertTrue($lazy->isLazyObjectInitialized()); + } + + /** + * @requires PHP 8.4 + */ + public function testMapInitializesNativePhp84LazyObject() + { + $initialized = false; + $initializer = function () use (&$initialized) { + $initialized = true; + + $p = new MyProxy(); + $p->name = 'test'; + + return $p; + }; + + $r = new \ReflectionClass(MyProxy::class); + $lazyObj = $r->newLazyProxy($initializer); + $this->assertFalse($initialized); + $mapper = new ObjectMapper(); + $d = $mapper->map($lazyObj, MyProxy::class); + $this->assertSame('test', $d->name); + $this->assertTrue($initialized); + } + + /** + * @dataProvider validPartialInputProvider + */ + public function testMapPartially(PartialInput $actual, FinalInput $expected) + { + $mapper = new ObjectMapper(); + $this->assertEquals($expected, $mapper->map($actual)); + } + + public static function validPartialInputProvider(): iterable + { + $p = new PartialInput(); + $p->uuid = '6a9eb6dd-c4dc-4746-bb99-f6bad716acb2'; + $p->website = 'https://updated.website.com'; + + $f = new FinalInput(); + $f->uuid = $p->uuid; + $f->website = $p->website; + + yield [$p, $f]; + + $p = new PartialInput(); + $p->uuid = '6a9eb6dd-c4dc-4746-bb99-f6bad716acb2'; + $p->website = null; + + $f = new FinalInput(); + $f->uuid = $p->uuid; + + yield [$p, $f]; + + $p = new PartialInput(); + $p->uuid = '6a9eb6dd-c4dc-4746-bb99-f6bad716acb2'; + $p->website = 'https://updated.website.com'; + $p->email = 'updated@email.com'; + + $f = new FinalInput(); + $f->uuid = $p->uuid; + $f->website = $p->website; + $f->email = $p->email; + + yield [$p, $f]; + } } diff --git a/src/Symfony/Component/ObjectMapper/TransformCallableInterface.php b/src/Symfony/Component/ObjectMapper/TransformCallableInterface.php index f8c296b4c26d5..e2056b993bbce 100644 --- a/src/Symfony/Component/ObjectMapper/TransformCallableInterface.php +++ b/src/Symfony/Component/ObjectMapper/TransformCallableInterface.php @@ -24,8 +24,8 @@ interface TransformCallableInterface { /** - * @param mixed $value The value being mapped - * @param T $source The object we're working on + * @param mixed $value The value being mapped + * @param T $source The object we're working on * @param T2|null $target The target we're mapping to */ public function __invoke(mixed $value, object $source, ?object $target): mixed; diff --git a/src/Symfony/Component/ObjectMapper/composer.json b/src/Symfony/Component/ObjectMapper/composer.json index 6d1b445d92781..0c7fc098992c6 100644 --- a/src/Symfony/Component/ObjectMapper/composer.json +++ b/src/Symfony/Component/ObjectMapper/composer.json @@ -20,7 +20,8 @@ "psr/container": "^2.0" }, "require-dev": { - "symfony/property-access": "^7.2" + "symfony/property-access": "^7.2", + "symfony/var-exporter": "^7.2" }, "autoload": { "psr-4": { diff --git a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php index 411e161696c43..b375cb0249d8a 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php +++ b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php @@ -1443,7 +1443,7 @@ public function testNormalizerCanAccessOtherOptions() $this->resolver->setDefault('norm', 'baz'); $this->resolver->setNormalizer('norm', function (Options $options) { - /* @var TestCase $test */ + /** @var TestCase $test */ Assert::assertSame('bar', $options['default']); return 'normalized'; @@ -1461,7 +1461,7 @@ public function testNormalizerCanAccessLazyOptions() $this->resolver->setDefault('norm', 'baz'); $this->resolver->setNormalizer('norm', function (Options $options) { - /* @var TestCase $test */ + /** @var TestCase $test */ Assert::assertEquals('bar', $options['lazy']); return 'normalized'; diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php index c860485e8925b..30e3ab8122a1e 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessorBuilder.php @@ -128,7 +128,7 @@ public function disableMagicSet(): static */ public function isMagicCallEnabled(): bool { - return (bool) ($this->magicMethods & PropertyAccessor::MAGIC_CALL); + return $this->magicMethods & PropertyAccessor::MAGIC_CALL; } /** diff --git a/src/Symfony/Component/PropertyAccess/PropertyPath.php b/src/Symfony/Component/PropertyAccess/PropertyPath.php index e797ab77be07c..71b90fc465967 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPath.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPath.php @@ -72,7 +72,7 @@ public function __construct(self|string $propertyPath) { // Can be used as copy constructor if ($propertyPath instanceof self) { - /* @var PropertyPath $propertyPath */ + /** @var PropertyPath $propertyPath */ $this->elements = $propertyPath->elements; $this->length = $propertyPath->length; $this->isIndex = $propertyPath->isIndex; diff --git a/src/Symfony/Component/RateLimiter/RateLimiterFactory.php b/src/Symfony/Component/RateLimiter/RateLimiterFactory.php index f9d0ca9a7386e..f16b8574029d9 100644 --- a/src/Symfony/Component/RateLimiter/RateLimiterFactory.php +++ b/src/Symfony/Component/RateLimiter/RateLimiterFactory.php @@ -63,11 +63,11 @@ private static function configureOptions(OptionsResolver $options): void try { $nowPlusInterval = @$now->modify('+'.$interval); } catch (\DateMalformedStringException $e) { - throw new \LogicException(\sprintf('Cannot parse interval "%s", please use a valid unit as described on https://www.php.net/datetime.formats.relative.', $interval), 0, $e); + throw new \LogicException(\sprintf('Cannot parse interval "%s", please use a valid unit as described on https://php.net/datetime.formats#datetime.formats.relative', $interval), 0, $e); } if (!$nowPlusInterval) { - throw new \LogicException(\sprintf('Cannot parse interval "%s", please use a valid unit as described on https://www.php.net/datetime.formats.relative.', $interval)); + throw new \LogicException(\sprintf('Cannot parse interval "%s", please use a valid unit as described on https://php.net/datetime.formats#datetime.formats.relative', $interval)); } return $now->diff($nowPlusInterval); diff --git a/src/Symfony/Component/RateLimiter/Tests/LimiterTest.php b/src/Symfony/Component/RateLimiter/Tests/LimiterTest.php index cc6822dcdbaef..476057b0aaa15 100644 --- a/src/Symfony/Component/RateLimiter/Tests/LimiterTest.php +++ b/src/Symfony/Component/RateLimiter/Tests/LimiterTest.php @@ -49,7 +49,7 @@ public function testFixedWindow() public function testWrongInterval() { $this->expectException(\LogicException::class); - $this->expectExceptionMessage('Cannot parse interval "1 minut", please use a valid unit as described on https://www.php.net/datetime.formats.relative.'); + $this->expectExceptionMessage('Cannot parse interval "1 minut", please use a valid unit as described on https://php.net/datetime.formats#datetime.formats.relative'); $this->createFactory([ 'id' => 'test', diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 0c2756e48be49..6448a75e729f9 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -1000,6 +1000,30 @@ public function testUtf8VarName() $this->assertEquals(['_route' => 'foo', 'bär' => 'baz', 'bäz' => 'foo'], $matcher->match('/foo/baz')); } + public function testParameterWithRequirementWithDefault() + { + $collection = new RouteCollection(); + + $route = new Route('/test/{foo}', ['foo' => 'foo-'], ['foo' => '\w+']); + $collection->add('test', $route); + + $matcher = $this->getUrlMatcher($collection); + + $result = $matcher->match('/test/foo'); + $this->assertSame('test', $result['_route']); + $this->assertSame('foo', $result['foo']); + + try { + $matcher->match('/test/foo-'); + } catch (ResourceNotFoundException $e) { + $this->assertStringContainsString('No routes found', $e->getMessage()); + } + + $result = $matcher->match('/test'); + $this->assertSame('test', $result['_route']); + $this->assertSame('foo-', $result['foo']); + } + public function testMapping() { $collection = new RouteCollection(); diff --git a/src/Symfony/Component/Scheduler/DependencyInjection/AddScheduleMessengerPass.php b/src/Symfony/Component/Scheduler/DependencyInjection/AddScheduleMessengerPass.php index 696422e0d28da..03d73a7c333a5 100644 --- a/src/Symfony/Component/Scheduler/DependencyInjection/AddScheduleMessengerPass.php +++ b/src/Symfony/Component/Scheduler/DependencyInjection/AddScheduleMessengerPass.php @@ -58,7 +58,9 @@ public function process(ContainerBuilder $container): void if ($serviceDefinition->hasTag('console.command')) { /** @var AsCommand|null $attribute */ $attribute = ($container->getReflectionClass($serviceDefinition->getClass())->getAttributes(AsCommand::class)[0] ?? null)?->newInstance(); - $message = new Definition(RunCommandMessage::class, [$attribute?->name ?? $serviceDefinition->getClass()::getDefaultName().(empty($tagAttributes['arguments']) ? '' : " {$tagAttributes['arguments']}")]); + $commandName = $attribute?->name ?? $serviceDefinition->getClass()::getDefaultName(); + + $message = new Definition(RunCommandMessage::class, [$commandName.($tagAttributes['arguments'] ? " {$tagAttributes['arguments']}" : '')]); } else { $message = new Definition(ServiceCallMessage::class, [$serviceId, $tagAttributes['method'] ?? '__invoke', (array) ($tagAttributes['arguments'] ?? [])]); } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 683e46d4e0eb8..d730c1118becb 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Security\Core\Authentication\Token; -use Symfony\Component\Security\Core\User\EquatableInterface; use Symfony\Component\Security\Core\User\InMemoryUser; use Symfony\Component\Security\Core\User\UserInterface; diff --git a/src/Symfony/Component/Security/Core/User/ChainUserChecker.php b/src/Symfony/Component/Security/Core/User/ChainUserChecker.php index eb9ff3384cf82..37ce0f0445836 100644 --- a/src/Symfony/Component/Security/Core/User/ChainUserChecker.php +++ b/src/Symfony/Component/Security/Core/User/ChainUserChecker.php @@ -29,16 +29,15 @@ public function checkPreAuth(UserInterface $user): void } } - public function checkPostAuth(UserInterface $user /* , TokenInterface $token */): void + /** + * @param ?TokenInterface $token + */ + public function checkPostAuth(UserInterface $user /* , ?TokenInterface $token = null */): void { $token = 1 < \func_num_args() ? func_get_arg(1) : null; foreach ($this->checkers as $checker) { - if ($token instanceof TokenInterface) { - $checker->checkPostAuth($user, $token); - } else { - $checker->checkPostAuth($user); - } + $checker->checkPostAuth($user, $token); } } } diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserChecker.php b/src/Symfony/Component/Security/Core/User/InMemoryUserChecker.php index 61367c2c1af9c..45b3335885fb3 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserChecker.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserChecker.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Core\User; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\DisabledException; /** @@ -33,7 +34,10 @@ public function checkPreAuth(UserInterface $user): void } } - public function checkPostAuth(UserInterface $user): void + /** + * @param ?TokenInterface $token + */ + public function checkPostAuth(UserInterface $user /* , ?TokenInterface $token = null */): void { } } diff --git a/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php b/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php index 43f1651e3e420..aea958fc69e7b 100644 --- a/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php +++ b/src/Symfony/Component/Security/Core/User/UserCheckerInterface.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Core\User; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AccountStatusException; /** @@ -33,7 +34,9 @@ public function checkPreAuth(UserInterface $user): void; /** * Checks the user account after authentication. * + * @param ?TokenInterface $token + * * @throws AccountStatusException */ - public function checkPostAuth(UserInterface $user /* , TokenInterface $token */): void; + public function checkPostAuth(UserInterface $user /* , ?TokenInterface $token = null */): void; } diff --git a/src/Symfony/Component/Security/Http/EventListener/IsCsrfTokenValidAttributeListener.php b/src/Symfony/Component/Security/Http/EventListener/IsCsrfTokenValidAttributeListener.php index 3075e3d07954b..336b794f512a0 100644 --- a/src/Symfony/Component/Security/Http/EventListener/IsCsrfTokenValidAttributeListener.php +++ b/src/Symfony/Component/Security/Http/EventListener/IsCsrfTokenValidAttributeListener.php @@ -45,7 +45,7 @@ public function onKernelControllerArguments(ControllerArgumentsEvent $event): vo foreach ($attributes as $attribute) { $id = $this->getTokenId($attribute->id, $request, $arguments); - $methods = \array_map('strtoupper', (array) $attribute->methods); + $methods = array_map('strtoupper', (array) $attribute->methods); if ($methods && !\in_array($request->getMethod(), $methods, true)) { continue; diff --git a/src/Symfony/Component/Security/Http/LoginLink/LoginLinkHandler.php b/src/Symfony/Component/Security/Http/LoginLink/LoginLinkHandler.php index 671a3850bccd9..61f43018991c7 100644 --- a/src/Symfony/Component/Security/Http/LoginLink/LoginLinkHandler.php +++ b/src/Symfony/Component/Security/Http/LoginLink/LoginLinkHandler.php @@ -84,14 +84,14 @@ public function consumeLoginLink(Request $request): UserInterface if (!$hash = $request->get('hash')) { throw new InvalidLoginLinkException('Missing "hash" parameter.'); } - if (!is_string($hash)) { + if (!\is_string($hash)) { throw new InvalidLoginLinkException('Invalid "hash" parameter.'); } if (!$expires = $request->get('expires')) { throw new InvalidLoginLinkException('Missing "expires" parameter.'); } - if (preg_match('/^\d+$/', $expires) !== 1) { + if (!preg_match('/^\d+$/', $expires)) { throw new InvalidLoginLinkException('Invalid "expires" parameter.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/FirewallTest.php b/src/Symfony/Component/Security/Http/Tests/FirewallTest.php index 89040f3875f2b..211269af9656a 100644 --- a/src/Symfony/Component/Security/Http/Tests/FirewallTest.php +++ b/src/Symfony/Component/Security/Http/Tests/FirewallTest.php @@ -104,9 +104,11 @@ public function testListenersAreCalled() { $calledListeners = []; - $callableListener = static function() use(&$calledListeners) { $calledListeners[] = 'callableListener'; }; + $callableListener = static function () use (&$calledListeners) { $calledListeners[] = 'callableListener'; }; $firewallListener = new class($calledListeners) implements FirewallListenerInterface { - public function __construct(private array &$calledListeners) {} + public function __construct(private array &$calledListeners) + { + } public function supports(Request $request): ?bool { @@ -124,7 +126,9 @@ public static function getPriority(): int } }; $callableFirewallListener = new class($calledListeners) extends AbstractListener { - public function __construct(private array &$calledListeners) {} + public function __construct(private array &$calledListeners) + { + } public function supports(Request $request): ?bool { diff --git a/src/Symfony/Component/Serializer/Context/Encoder/JsonEncoderContextBuilder.php b/src/Symfony/Component/Serializer/Context/Encoder/JsonEncoderContextBuilder.php index 0ebd7026984e3..8920dddb37eda 100644 --- a/src/Symfony/Component/Serializer/Context/Encoder/JsonEncoderContextBuilder.php +++ b/src/Symfony/Component/Serializer/Context/Encoder/JsonEncoderContextBuilder.php @@ -28,7 +28,7 @@ final class JsonEncoderContextBuilder implements ContextBuilderInterface /** * Configures the json_encode flags bitmask. * - * @see https://www.php.net/manual/en/json.constants.php + * @see https://php.net/json.constants * * @param positive-int|null $options */ @@ -40,7 +40,7 @@ public function withEncodeOptions(?int $options): static /** * Configures the json_decode flags bitmask. * - * @see https://www.php.net/manual/en/json.constants.php + * @see https://php.net/json.constants * * @param positive-int|null $options */ diff --git a/src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php b/src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php index 7a5097e94518b..9d0159c064b09 100644 --- a/src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php +++ b/src/Symfony/Component/Serializer/Context/Encoder/XmlEncoderContextBuilder.php @@ -36,7 +36,7 @@ public function withAsCollection(?bool $asCollection): static /** * Configures node types to ignore while decoding. * - * @see https://www.php.net/manual/en/dom.constants.php + * @see https://php.net/dom.constants * * @param list|null $decoderIgnoredNodeTypes */ @@ -48,7 +48,7 @@ public function withDecoderIgnoredNodeTypes(?array $decoderIgnoredNodeTypes): st /** * Configures node types to ignore while encoding. * - * @see https://www.php.net/manual/en/dom.constants.php + * @see https://php.net/dom.constants * * @param list|null $encoderIgnoredNodeTypes */ @@ -60,7 +60,7 @@ public function withEncoderIgnoredNodeTypes(?array $encoderIgnoredNodeTypes): st /** * Configures the DOMDocument encoding. * - * @see https://www.php.net/manual/en/class.domdocument.php#domdocument.props.encoding + * @see https://php.net/class.domdocument#domdocument.props.encoding */ public function withEncoding(?string $encoding): static { @@ -70,7 +70,7 @@ public function withEncoding(?string $encoding): static /** * Configures whether to encode with indentation and extra space. * - * @see https://php.net/manual/en/class.domdocument.php#domdocument.props.formatoutput + * @see https://php.net/class.domdocument#domdocument.props.formatoutput */ public function withFormatOutput(?bool $formatOutput): static { @@ -80,7 +80,7 @@ public function withFormatOutput(?bool $formatOutput): static /** * Configures the DOMDocument::loadXml options bitmask. * - * @see https://www.php.net/manual/en/libxml.constants.php + * @see https://php.net/libxml.constants * * @param positive-int|null $loadOptions */ @@ -92,7 +92,7 @@ public function withLoadOptions(?int $loadOptions): static /** * Configures the DOMDocument::saveXml options bitmask. * - * @see https://www.php.net/manual/en/libxml.constants.php + * @see https://php.net/libxml.constants * * @param positive-int|null $saveOptions */ @@ -120,7 +120,7 @@ public function withRootNodeName(?string $rootNodeName): static /** * Configures whether the document will be standalone. * - * @see https://php.net/manual/en/class.domdocument.php#domdocument.props.xmlstandalone + * @see https://php.net/class.domdocument#domdocument.props.xmlstandalone */ public function withStandalone(?bool $standalone): static { @@ -138,7 +138,7 @@ public function withTypeCastAttributes(?bool $typeCastAttributes): static /** * Configures the version number of the document. * - * @see https://php.net/manual/en/class.domdocument.php#domdocument.props.xmlversion + * @see https://php.net/class.domdocument#domdocument.props.xmlversion */ public function withVersion(?string $version): static { diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index d9a50fef0cbd2..6fec439b9a09b 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -1208,6 +1208,10 @@ private function getMappedClass(array $data, string $class, array $context): str throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('Type property "%s" not found for the abstract object "%s".', $mapping->getTypeProperty(), $class), null, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(), false); } + if (!\is_string($type) && (!\is_object($type) || !method_exists($type, '__toString'))) { + throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type property "%s" for the abstract object "%s" must be a string or a stringable object.', $mapping->getTypeProperty(), $class), $type, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(), false); + } + if (null === $mappedClass = $mapping->getClassForType($type)) { throw NotNormalizableValueException::createForUnexpectedDataType(\sprintf('The type "%s" is not a valid value.', $type), $type, ['string'], isset($context['deserialization_path']) ? $context['deserialization_path'].'.'.$mapping->getTypeProperty() : $mapping->getTypeProperty(), true); } diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index 1619f35bf4d7a..979e95e021e21 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -13,6 +13,7 @@ use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; @@ -181,7 +182,22 @@ protected function setAttributeValue(object $object, string $attribute, mixed $v return; } - $reflectionProperty->setValue($object, $value); + if (!$reflectionProperty->isReadOnly()) { + $reflectionProperty->setValue($object, $value); + + return; + } + + if (!$reflectionProperty->isInitialized($object)) { + $declaringClass = $reflectionProperty->getDeclaringClass(); + $declaringClass->getProperty($reflectionProperty->getName())->setValue($object, $value); + + return; + } + + if ($reflectionProperty->getValue($object) !== $value) { + throw new LogicException(\sprintf('Attempting to change readonly property "%s"::$%s.', $object::class, $reflectionProperty->getName())); + } } /** diff --git a/src/Symfony/Component/Serializer/SerializerInterface.php b/src/Symfony/Component/Serializer/SerializerInterface.php index 7ee63a7772443..f9fff7f844b22 100644 --- a/src/Symfony/Component/Serializer/SerializerInterface.php +++ b/src/Symfony/Component/Serializer/SerializerInterface.php @@ -40,10 +40,10 @@ public function serialize(mixed $data, string $format, array $context = []): str * @param TType $type * @param array $context * - * @psalm-return (TType is class-string ? TObject : mixed) - * * @phpstan-return ($type is class-string ? TObject : mixed) * + * @psalm-return (TType is class-string ? TObject : mixed) + * * @throws NotNormalizableValueException Occurs when a value cannot be denormalized * @throws UnexpectedValueException Occurs when a value cannot be decoded * @throws ExceptionInterface Occurs for all the other cases of serialization-related errors diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/AbstractDummyFirstChild.php b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/AbstractDummyFirstChild.php index b5cd2faba24ee..cb9cb0abbe347 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/AbstractDummyFirstChild.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/Attributes/AbstractDummyFirstChild.php @@ -16,6 +16,7 @@ class AbstractDummyFirstChild extends AbstractDummy { public $bar; + public $baz; /** @var DummyFirstChildQuux|null */ public $quux; diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/BookDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/BookDummy.php new file mode 100644 index 0000000000000..2b62667c0dbc3 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/BookDummy.php @@ -0,0 +1,27 @@ + + * + * 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 BookDummy +{ + public function __construct( + public private(set) string $title, + public protected(set) string $author, + protected private(set) int $pubYear, + ) { + } + + public function getPubYear(): int + { + return $this->pubYear; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/ChildClassDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/ChildClassDummy.php new file mode 100644 index 0000000000000..f8d4f0743a4c4 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/ChildClassDummy.php @@ -0,0 +1,17 @@ + + * + * 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; + +readonly class ChildClassDummy extends ParentClassDummy +{ + public string $childProp; +} diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/ParentClassDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/ParentClassDummy.php new file mode 100644 index 0000000000000..730d71aecfec9 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/ParentClassDummy.php @@ -0,0 +1,22 @@ + + * + * 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; + +readonly class ParentClassDummy +{ + private string $parentProp; + + public function getParentProp(): string + { + return $this->parentProp; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/SpecialBookDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/SpecialBookDummy.php new file mode 100644 index 0000000000000..44679e2f205f0 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/SpecialBookDummy.php @@ -0,0 +1,16 @@ + + * + * 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 SpecialBookDummy extends BookDummy +{ +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 50b9e2a83c26c..a7cef4af335b4 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -528,6 +528,73 @@ private function getDenormalizerForStringCollection() return $denormalizer; } + /** + * @dataProvider provideInvalidDiscriminatorTypes + */ + public function testDenormalizeWithDiscriminatorMapHandlesInvalidTypeValue(mixed $typeValue, bool $shouldFail) + { + if ($shouldFail) { + $this->expectException(NotNormalizableValueException::class); + $this->expectExceptionMessage( + 'The type property "type" for the abstract object "Symfony\Component\Serializer\Tests\Fixtures\Attributes\AbstractDummy" must be a string or a stringable object.' + ); + } + + $factory = new ClassMetadataFactory(new AttributeLoader()); + + $loaderMock = new class implements ClassMetadataFactoryInterface { + public function getMetadataFor($value): ClassMetadataInterface + { + if (AbstractDummy::class === $value) { + return new ClassMetadata( + AbstractDummy::class, + new ClassDiscriminatorMapping('type', [ + 'first' => AbstractDummyFirstChild::class, + 'second' => AbstractDummySecondChild::class, + ]) + ); + } + + throw new InvalidArgumentException(); + } + + public function hasMetadataFor($value): bool + { + return AbstractDummy::class === $value; + } + }; + + $discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock); + $normalizer = new AbstractObjectNormalizerDummy($factory, null, new ReflectionExtractor(), $discriminatorResolver); + $serializer = new Serializer([$normalizer]); + $normalizer->setSerializer($serializer); + $normalizedData = $normalizer->denormalize(['foo' => 'foo', 'baz' => 'baz', 'quux' => ['value' => 'quux'], 'type' => $typeValue], AbstractDummy::class); + + $this->assertInstanceOf(DummyFirstChildQuux::class, $normalizedData->quux); + } + + /** + * @return iterable + */ + public static function provideInvalidDiscriminatorTypes(): array + { + $toStringObject = new class { + public function __toString() + { + return 'first'; + } + }; + + return [ + [[], true], + [new \stdClass(), true], + [123, true], + [false, true], + ['first', false], + [$toStringObject, false], + ]; + } + public function testDenormalizeWithDiscriminatorMapUsesCorrectClassname() { $factory = new ClassMetadataFactory(new AttributeLoader()); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php index ecdae436e219a..30b8f85f056ed 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php @@ -30,10 +30,12 @@ use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummy; use Symfony\Component\Serializer\Tests\Fixtures\Attributes\GroupDummyChild; +use Symfony\Component\Serializer\Tests\Fixtures\ChildClassDummy; use Symfony\Component\Serializer\Tests\Fixtures\Dummy; use Symfony\Component\Serializer\Tests\Fixtures\Php74Dummy; use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy; use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder; +use Symfony\Component\Serializer\Tests\Fixtures\SpecialBookDummy; use Symfony\Component\Serializer\Tests\Normalizer\Features\CacheableObjectAttributesTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\CallbacksTestTrait; use Symfony\Component\Serializer\Tests\Normalizer\Features\CircularReferenceTestTrait; @@ -176,6 +178,39 @@ public function testDenormalize() $this->assertEquals('bar', $obj->getBar()); } + /** + * @requires PHP 8.2 + */ + public function testDenormalizeWithReadOnlyClass() + { + /** @var ChildClassDummy $object */ + $object = $this->normalizer->denormalize( + ['parentProp' => 'parentProp', 'childProp' => 'childProp'], + ChildClassDummy::class, + 'any' + ); + + $this->assertSame('parentProp', $object->getParentProp()); + $this->assertSame('childProp', $object->childProp); + } + + /** + * @requires PHP 8.4 + */ + public function testDenormalizeWithAsymmetricPropertyVisibility() + { + /** @var SpecialBookDummy $object */ + $object = $this->normalizer->denormalize( + ['title' => 'life', 'author' => 'Santiago San Martin', 'pubYear' => 2000], + SpecialBookDummy::class, + 'any' + ); + + $this->assertSame('life', $object->title); + $this->assertSame('Santiago San Martin', $object->author); + $this->assertSame(2000, $object->getPubYear()); + } + public function testNormalizeWithParentClass() { $group = new GroupDummyChild(); diff --git a/src/Symfony/Component/Serializer/Tests/SerializerTest.php b/src/Symfony/Component/Serializer/Tests/SerializerTest.php index d6502f8adacd7..255a745f039bd 100644 --- a/src/Symfony/Component/Serializer/Tests/SerializerTest.php +++ b/src/Symfony/Component/Serializer/Tests/SerializerTest.php @@ -454,7 +454,7 @@ public function hasMetadataFor($value): bool $discriminatorResolver = new ClassDiscriminatorFromClassMetadata($loaderMock); $serializer = new Serializer([new ObjectNormalizer(null, null, null, new PhpDocExtractor(), $discriminatorResolver)], ['json' => new JsonEncoder()]); - $jsonData = '{"type":"first","quux":{"value":"quux"},"bar":"bar-value","foo":"foo-value"}'; + $jsonData = '{"type":"first","quux":{"value":"quux"},"bar":"bar-value","baz":null,"foo":"foo-value"}'; $deserialized = $serializer->deserialize($jsonData, AbstractDummy::class, 'json'); $this->assertEquals($example, $deserialized); diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index d8809fa079ef9..1c4d384b6be9b 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -38,7 +38,7 @@ "symfony/property-access": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/type-info": "^7.1", + "symfony/type-info": "^7.1.8", "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", "symfony/var-dumper": "^6.4|^7.0", diff --git a/src/Symfony/Component/String/Tests/Slugger/AsciiSluggerTest.php b/src/Symfony/Component/String/Tests/Slugger/AsciiSluggerTest.php index 7604f3bcde645..b78baf33de9a2 100644 --- a/src/Symfony/Component/String/Tests/Slugger/AsciiSluggerTest.php +++ b/src/Symfony/Component/String/Tests/Slugger/AsciiSluggerTest.php @@ -112,7 +112,7 @@ public static function provideSlugEmojiTests(): iterable */ public function testSlugEmojiWithSetLocale() { - if (!setlocale(LC_ALL, 'C.UTF-8')) { + if (!setlocale(\LC_ALL, 'C.UTF-8')) { $this->markTestSkipped('Unable to switch to the "C.UTF-8" locale.'); } diff --git a/src/Symfony/Component/Translation/Bridge/Crowdin/CrowdinProvider.php b/src/Symfony/Component/Translation/Bridge/Crowdin/CrowdinProvider.php index 55b676a028ccd..56c214144ea14 100644 --- a/src/Symfony/Component/Translation/Bridge/Crowdin/CrowdinProvider.php +++ b/src/Symfony/Component/Translation/Bridge/Crowdin/CrowdinProvider.php @@ -124,7 +124,7 @@ public function read(array $domains, array $locales): TranslatorBag } } - /* @var ResponseInterface $response */ + /** @var ResponseInterface $response */ $downloads = []; foreach ($responses as [$response, $locale, $domain]) { if (204 === $response->getStatusCode()) { diff --git a/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php b/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php index 990caee166902..4199f596771b9 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php @@ -46,9 +46,9 @@ protected function deleteTmpDir() continue; } if ($path->isDir()) { - rmdir($path->__toString()); + @rmdir($path->__toString()); } else { - unlink($path->__toString()); + @unlink($path->__toString()); } } rmdir($this->tmpDir); diff --git a/src/Symfony/Component/Translation/TranslatableMessage.php b/src/Symfony/Component/Translation/TranslatableMessage.php index 74b77f68595d4..3c4986a67a7d1 100644 --- a/src/Symfony/Component/Translation/TranslatableMessage.php +++ b/src/Symfony/Component/Translation/TranslatableMessage.php @@ -48,9 +48,13 @@ public function getDomain(): ?string public function trans(TranslatorInterface $translator, ?string $locale = null): string { - return $translator->trans($this->getMessage(), array_map( - static fn ($parameter) => $parameter instanceof TranslatableInterface ? $parameter->trans($translator, $locale) : $parameter, - $this->getParameters() - ), $this->getDomain(), $locale); + $parameters = $this->getParameters(); + foreach ($parameters as $k => $v) { + if ($v instanceof TranslatableInterface) { + $parameters[$k] = $v->trans($translator, $locale); + } + } + + return $translator->trans($this->getMessage(), $parameters, $this->getDomain(), $locale); } } diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 4ce3edad3e97b..0553da7d70424 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -201,7 +201,7 @@ public function trans(?string $id, array $parameters = [], ?string $domain = nul } } - if (null === $globalParameters =& $this->globalTranslatedParameters[$locale]) { + if (null === $globalParameters = &$this->globalTranslatedParameters[$locale]) { $globalParameters = $this->globalParameters; foreach ($globalParameters as $key => $value) { if ($value instanceof TranslatableInterface) { diff --git a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithTypeAliases.php b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithTypeAliases.php index 7f73190df1549..85f5784dd2cfe 100644 --- a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithTypeAliases.php +++ b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyWithTypeAliases.php @@ -57,6 +57,17 @@ final class DummyWithTypeAliases public mixed $psalmOtherAliasedExternalAlias; } +/** + * @phpstan-import-type CustomInt from DummyWithPhpDoc + */ +final class DummyWithImportedOnlyTypeAliases +{ + /** + * @var CustomInt + */ + public mixed $externalAlias; +} + /** * @phpstan-type Foo = array{0: Bar} * @phpstan-type Bar = array{0: Foo} diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeContext/TypeContextFactoryTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeContext/TypeContextFactoryTest.php index cf0f1bb91179f..532ba3984250e 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeContext/TypeContextFactoryTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeContext/TypeContextFactoryTest.php @@ -15,6 +15,7 @@ use Symfony\Component\TypeInfo\Exception\LogicException; use Symfony\Component\TypeInfo\Tests\Fixtures\AbstractDummy; use Symfony\Component\TypeInfo\Tests\Fixtures\Dummy; +use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithImportedOnlyTypeAliases; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithInvalidTypeAlias; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithInvalidTypeAliasImport; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithRecursiveTypeAliases; @@ -179,6 +180,10 @@ public function testCollectTypeAliases() 'PsalmCustomArray' => Type::arrayShape([0 => Type::int(), 1 => Type::string(), 2 => Type::bool()]), 'PsalmAliasedCustomInt' => Type::int(), ], $this->typeContextFactory->createFromReflection(new \ReflectionProperty(DummyWithTypeAliases::class, 'localAlias'))->typeAliases); + + $this->assertEquals([ + 'CustomInt' => Type::int(), + ], $this->typeContextFactory->createFromReflection(new \ReflectionClass(DummyWithImportedOnlyTypeAliases::class))->typeAliases); } public function testDoNotCollectTypeAliasesWhenToStringTypeResolver() diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeFactoryTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeFactoryTest.php index 6a9aaf4cfe25b..9a59134b581fb 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeFactoryTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeFactoryTest.php @@ -254,6 +254,8 @@ public static function createFromValueProvider(): iterable yield [Type::object(\DateTimeImmutable::class), new \DateTimeImmutable()]; yield [Type::object(), new \stdClass()]; yield [Type::list(Type::object()), [new \stdClass(), new \DateTimeImmutable()]]; + yield [Type::enum(DummyEnum::class), DummyEnum::ONE]; + yield [Type::enum(DummyBackedEnum::class), DummyBackedEnum::ONE]; // collection $arrayAccess = new class implements \ArrayAccess { @@ -276,6 +278,7 @@ public function offsetUnset(mixed $offset): void } }; + yield [Type::array(Type::mixed()), []]; yield [Type::list(Type::int()), [1, 2, 3]]; yield [Type::dict(Type::bool()), ['a' => true, 'b' => false]]; yield [Type::array(Type::string()), [1 => 'foo', 'bar' => 'baz']]; diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php index 3b194128661c9..cca88b552acfd 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php @@ -103,12 +103,12 @@ public static function resolveDataProvider(): iterable yield [Type::int(), DummyWithConstants::class.'::DUMMY_INT_*']; yield [Type::int(), DummyWithConstants::class.'::DUMMY_INT_A']; yield [Type::float(), DummyWithConstants::class.'::DUMMY_FLOAT_*']; - yield [Type::bool(), DummyWithConstants::class.'::DUMMY_TRUE_*']; - yield [Type::bool(), DummyWithConstants::class.'::DUMMY_FALSE_*']; + yield [Type::true(), DummyWithConstants::class.'::DUMMY_TRUE_*']; + yield [Type::false(), DummyWithConstants::class.'::DUMMY_FALSE_*']; yield [Type::null(), DummyWithConstants::class.'::DUMMY_NULL_*']; - yield [Type::array(), DummyWithConstants::class.'::DUMMY_ARRAY_*']; + yield [Type::array(null, Type::union(Type::int(), Type::string())), DummyWithConstants::class.'::DUMMY_ARRAY_*']; yield [Type::enum(DummyEnum::class, Type::string()), DummyWithConstants::class.'::DUMMY_ENUM_*']; - yield [Type::union(Type::string(), Type::int(), Type::float(), Type::bool(), Type::null(), Type::array(), Type::enum(DummyEnum::class, Type::string())), DummyWithConstants::class.'::DUMMY_MIX_*']; + yield [Type::union(Type::enum(DummyEnum::class, Type::string()), Type::array(Type::mixed(), Type::union(Type::int(), Type::string())), Type::string(), Type::int(), Type::float(), Type::bool(), Type::null()), DummyWithConstants::class.'::DUMMY_MIX_*']; // identifiers yield [Type::bool(), 'bool']; diff --git a/src/Symfony/Component/TypeInfo/TypeContext/TypeContextFactory.php b/src/Symfony/Component/TypeInfo/TypeContext/TypeContextFactory.php index 8e1cc3d4314e7..a7564557e555c 100644 --- a/src/Symfony/Component/TypeInfo/TypeContext/TypeContextFactory.php +++ b/src/Symfony/Component/TypeInfo/TypeContext/TypeContextFactory.php @@ -241,7 +241,7 @@ private function collectTypeAliases(\ReflectionClass $reflection, TypeContext $t private function resolveTypeAliases(array $toResolve, array $resolved, TypeContext $typeContext): array { if (!$toResolve) { - return []; + return $resolved; } $typeContext = new TypeContext( diff --git a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php index b922c2749ba5d..47af50eb89099 100644 --- a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php +++ b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php @@ -412,6 +412,7 @@ public static function fromValue(mixed $value): Type } $type = match (true) { + $value instanceof \UnitEnum => Type::enum($value::class), \is_object($value) => \stdClass::class === $value::class ? self::object() : self::object($value::class), \is_array($value) => self::builtin(TypeIdentifier::ARRAY), default => null, @@ -428,8 +429,6 @@ public static function fromValue(mixed $value): Type /** @var list $valueTypes */ $valueTypes = []; - $i = 0; - foreach ($value as $k => $v) { $keyTypes[] = self::fromValue($k); $valueTypes[] = self::fromValue($v); @@ -444,7 +443,7 @@ public static function fromValue(mixed $value): Type $valueType = $valueTypes ? CollectionType::mergeCollectionValueTypes($valueTypes) : Type::mixed(); - return self::collection($type, $valueType, $keyType, \is_array($value) && array_is_list($value)); + return self::collection($type, $valueType, $keyType, \is_array($value) && [] !== $value && array_is_list($value)); } if ($value instanceof \ArrayAccess) { diff --git a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php index 844de98963e3d..1ae865e783eb1 100644 --- a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php +++ b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php @@ -149,29 +149,11 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ foreach ((new \ReflectionClass($className))->getReflectionConstants() as $const) { if (preg_match('/^'.str_replace('\*', '.*', preg_quote($node->constExpr->name, '/')).'$/', $const->getName())) { - $constValue = $const->getValue(); - - $types[] = match (true) { - true === $constValue, - false === $constValue => Type::bool(), - null === $constValue => Type::null(), - \is_string($constValue) => Type::string(), - \is_int($constValue) => Type::int(), - \is_float($constValue) => Type::float(), - \is_array($constValue) => Type::array(), - $constValue instanceof \UnitEnum => Type::enum($constValue::class), - default => Type::mixed(), - }; + $types[] = Type::fromValue($const->getValue()); } } - $types = array_unique($types); - - if (\count($types) > 2) { - return Type::union(...$types); - } - - return $types[0] ?? Type::null(); + return CollectionType::mergeCollectionValueTypes($types); } return match ($node->constExpr::class) { diff --git a/src/Symfony/Component/Validator/Constraints/CardScheme.php b/src/Symfony/Component/Validator/Constraints/CardScheme.php index a75e9f7abf7a4..81de342f5bbf0 100644 --- a/src/Symfony/Component/Validator/Constraints/CardScheme.php +++ b/src/Symfony/Component/Validator/Constraints/CardScheme.php @@ -66,7 +66,9 @@ public function __construct(array|string|null $schemes, ?string $message = null, $options = []; } - $options['value'] = $schemes; + if (null !== $schemes) { + $options['value'] = $schemes; + } } parent::__construct($options, $groups, $payload); diff --git a/src/Symfony/Component/Validator/Constraints/Collection.php b/src/Symfony/Component/Validator/Constraints/Collection.php index eca5a4eeecc86..b59caa89df873 100644 --- a/src/Symfony/Component/Validator/Constraints/Collection.php +++ b/src/Symfony/Component/Validator/Constraints/Collection.php @@ -45,13 +45,19 @@ class Collection extends Composite #[HasNamedArguments] public function __construct(mixed $fields = null, ?array $groups = null, mixed $payload = null, ?bool $allowExtraFields = null, ?bool $allowMissingFields = null, ?string $extraFieldsMessage = null, ?string $missingFieldsMessage = null) { + $options = $fields; + if (self::isFieldsOption($fields)) { - $fields = ['fields' => $fields]; + $options = []; + + if (null !== $fields) { + $options['fields'] = $fields; + } } else { trigger_deprecation('symfony/validator', '7.3', 'Passing an array of options to configure the "%s" constraint is deprecated, use named arguments instead.', static::class); } - parent::__construct($fields, $groups, $payload); + parent::__construct($options, $groups, $payload); $this->allowExtraFields = $allowExtraFields ?? $this->allowExtraFields; $this->allowMissingFields = $allowMissingFields ?? $this->allowMissingFields; @@ -88,6 +94,10 @@ protected function getCompositeOption(): string private static function isFieldsOption($options): bool { + if (null === $options) { + return true; + } + if (!\is_array($options)) { return false; } diff --git a/src/Symfony/Component/Validator/Constraints/Composite.php b/src/Symfony/Component/Validator/Constraints/Composite.php index ce6283b84f125..1710d9a49d231 100644 --- a/src/Symfony/Component/Validator/Constraints/Composite.php +++ b/src/Symfony/Component/Validator/Constraints/Composite.php @@ -58,7 +58,7 @@ public function __construct(mixed $options = null, ?array $groups = null, mixed $this->initializeNestedConstraints(); foreach ((array) $this->getCompositeOption() as $option) { - /* @var Constraint[] $nestedConstraints */ + /** @var Constraint[] $nestedConstraints */ $nestedConstraints = $this->$option; if (!\is_array($nestedConstraints)) { diff --git a/src/Symfony/Component/Validator/Constraints/Expression.php b/src/Symfony/Component/Validator/Constraints/Expression.php index a739acbb807b0..750c6f8fc79c6 100644 --- a/src/Symfony/Component/Validator/Constraints/Expression.php +++ b/src/Symfony/Component/Validator/Constraints/Expression.php @@ -71,7 +71,9 @@ public function __construct( $options = []; } - $options['value'] = $expression; + if (null !== $expression) { + $options['value'] = $expression; + } } parent::__construct($options, $groups, $payload); diff --git a/src/Symfony/Component/Validator/Constraints/When.php b/src/Symfony/Component/Validator/Constraints/When.php index f32b81a37dd3f..74601c1d121b4 100644 --- a/src/Symfony/Component/Validator/Constraints/When.php +++ b/src/Symfony/Component/Validator/Constraints/When.php @@ -57,7 +57,9 @@ public function __construct(string|Expression|array|\Closure $expression, array| } $options['expression'] = $expression; - $options['constraints'] = $constraints; + if (null !== $constraints) { + $options['constraints'] = $constraints; + } $options['otherwise'] = $otherwise; } diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf index e83aced818553..42e51903c974c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf @@ -4,15 +4,15 @@ This value should be false. - falseでなければなりません。 + falseである必要があります。 This value should be true. - trueでなければなりません。 + trueである必要があります。 This value should be of type {{ type }}. - 型は{{ type }}でなければなりません。 + {{ type }}型でなければなりません。 This value should be blank. @@ -32,27 +32,27 @@ One or more of the given values is invalid. - 無効な選択肢が含まれています。 + 無効な値が含まれています。 This field was not expected. - このフィールドは予期されていませんでした。 + このフィールドは不要です。 This field is missing. - このフィールドは、欠落しています。 + このフィールドを入力してください。 This value is not a valid date. - 有効な日付ではありません。 + 無効な日付です。 This value is not a valid datetime. - 有効な日時ではありません。 + 無効な日時です。 This value is not a valid email address. - 有効なメールアドレスではありません。 + 無効なメールアドレスです。 The file could not be found. @@ -60,11 +60,11 @@ The file is not readable. - ファイルを読み込めません。 + ファイルが読み込めません。 The file is too large ({{ size }} {{ suffix }}). Allowed maximum size is {{ limit }} {{ suffix }}. - ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。有効な最大サイズは{{ limit }} {{ suffix }}です。 + ファイルのサイズが大きすぎます({{ size }} {{ suffix }})。ファイルサイズは{{ limit }} {{ suffix }}以下にしてください。 The mime type of the file is invalid ({{ type }}). Allowed mime types are {{ types }}. @@ -76,7 +76,7 @@ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - 値が長すぎます。{{ limit }}文字以内でなければなりません。 + この値は、{{ limit }}文字以内で入力してください。 This value should be {{ limit }} or more. @@ -84,31 +84,31 @@ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - 値が短すぎます。{{ limit }}文字以上でなければなりません。 + この値は、{{ limit }}文字以上で入力してください。 This value should not be blank. - 空であってはなりません。 + 入力してください。 This value should not be null. - nullであってはなりません。 + 入力してください。 This value should be null. - nullでなければなりません。 + 入力しないでください。 This value is not valid. - 有効な値ではありません。 + 無効な値です。 This value is not a valid time. - 有効な時刻ではありません。 + 無効な時刻です。 This value is not a valid URL. - 有効なURLではありません。 + 無効なURLです。 The two values should be equal. @@ -128,7 +128,7 @@ This value should be a valid number. - 有効な数字ではありません。 + 有効な数値ではありません。 This file is not a valid image. @@ -136,11 +136,11 @@ This value is not a valid IP address. - 有効なIPアドレスではありません。 + 無効なIPアドレスです。 This value is not a valid language. - 有効な言語名ではありません。 + 無効な言語名です。 This value is not a valid locale. @@ -160,7 +160,7 @@ The image width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - 画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセルまでにしてください。 + 画像の幅が大きすぎます({{ width }}ピクセル)。{{ max_width }}ピクセル以下にしてください。 The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. @@ -168,7 +168,7 @@ The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - 画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセルまでにしてください。 + 画像の高さが大きすぎます({{ height }}ピクセル)。{{ max_height }}ピクセル以下にしてください。 The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. @@ -176,15 +176,15 @@ This value should be the user's current password. - ユーザーの現在のパスワードでなければなりません。 + 現在のパスワードを入力してください。 This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - ちょうど{{ limit }}文字でなければなりません。 + {{ limit }}文字ちょうどで入力してください。 The file was only partially uploaded. - ファイルのアップロードは完全ではありません。 + ファイルのアップロードに失敗しました。 No file was uploaded. @@ -200,15 +200,15 @@ A PHP extension caused the upload to fail. - PHP拡張によってアップロードに失敗しました。 + PHP拡張が原因でアップロードに失敗しました。 This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - {{ limit }}個以上の要素を含んでなければいけません。 + 少なくとも{{ limit }}個の要素を含む必要があります。 This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - 要素は{{ limit }}個までです。 + {{ limit }}個以下の要素を含む必要があります。 This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. @@ -220,7 +220,7 @@ Unsupported card type or invalid card number. - 未対応のカード種類又は無効なカード番号です。 + 未対応のカード種類または無効なカード番号です。 This value is not a valid International Bank Account Number (IBAN). @@ -236,7 +236,7 @@ This value is neither a valid ISBN-10 nor a valid ISBN-13. - 有効なISBN-10コード又はISBN-13コードではありません。 + 有効なISBN-10コードまたはISBN-13コードではありません。 This value is not a valid ISSN. @@ -244,11 +244,11 @@ This value is not a valid currency. - 有効な貨幣ではありません。 + 有効な通貨ではありません。 This value should be equal to {{ compared_value }}. - {{ compared_value }}と等しくなければなりません。 + {{ compared_value }}と同じ値でなければなりません。 This value should be greater than {{ compared_value }}. @@ -260,7 +260,7 @@ This value should be identical to {{ compared_value_type }} {{ compared_value }}. - {{ compared_value_type }}としての{{ compared_value }}と等しくなければなりません。 + この値は{{ compared_value_type }} {{ compared_value }}と同じでなければなりません。 This value should be less than {{ compared_value }}. @@ -276,7 +276,7 @@ This value should not be identical to {{ compared_value_type }} {{ compared_value }}. - {{ compared_value_type }}としての{{ compared_value }}と等しくてはいけません。 + この値は{{ compared_value_type }}の{{ compared_value }}と異なる値にしてください。 The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. @@ -300,7 +300,7 @@ An empty file is not allowed. - 空のファイルは許可されていません。 + 空のファイルは無効です。 The host could not be resolved. @@ -308,7 +308,7 @@ This value does not match the expected {{ charset }} charset. - この値は予期される文字コード({{ charset }})と異なります。 + 文字コードが{{ charset }}と一致しません。 This value is not a valid Business Identifier Code (BIC). @@ -332,7 +332,7 @@ This value should be valid JSON. - JSONでなければなりません。 + 有効なJSONでなければなりません。 This collection should contain only unique elements. @@ -360,7 +360,7 @@ This password has been leaked in a data breach, it must not be used. Please use another password. - このパスワードは漏洩している為使用できません。 + このパスワードは漏洩しているため使用できません。 This value should be between {{ min }} and {{ max }}. @@ -388,7 +388,7 @@ This value should be a valid expression. - 式でなければなりません。 + 有効な式でなければなりません。 This value is not a valid CSS color. @@ -400,11 +400,11 @@ The value of the netmask should be between {{ min }} and {{ max }}. - ネットマスクの値は、{{ min }}から{{ max }}の間にある必要があります。 + ネットマスクは{{ min }}から{{ max }}の範囲で入力してください。 The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. - ファイル名が長すぎます。ファイル名の長さは{{ filename_max_length }}文字以下でなければなりません。 + ファイル名が長すぎます。ファイル名は{{ filename_max_length }}文字以下でなければなりません。 The password strength is too low. Please use a stronger password. @@ -412,7 +412,7 @@ This value contains characters that are not allowed by the current restriction-level. - この値は現在の制限レベルで許可されていない文字を含んでいます。 + 現在の設定では使用できない文字が含まれています。 Using invisible characters is not allowed. @@ -444,31 +444,31 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - この値は短すぎます。{{ min }}単語以上にする必要があります。 + 短すぎます。{{ min }}単語以上にする必要があります。 This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - この値は長すぎます。{{ max }}単語以下にする必要があります。 + 長すぎます。{{ max }}単語以下にする必要があります。 This value does not represent a valid week in the ISO 8601 format. - この値は ISO 8601 形式の有効な週を表していません。 + 週の形式が正しくありません(ISO 8601形式)。 This value is not a valid week. - この値は有効な週ではありません。 + 無効な週形式です。 This value should not be before week "{{ min }}". - この値は週 "{{ min }}" より前であってはいけません。 + 週 "{{ min }}" 以降を指定してください。 This value should not be after week "{{ max }}". - この値は週 "{{ max }}" 以降であってはいけません。 + 週 "{{ max }}" までを指定してください。 This value is not a valid Twig template. - この値は有効な Twig テンプレートではありません。 + 有効なTwigテンプレートではありません。 diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf index 7c243a6b0ca02..04fe2fc1f1926 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.pl.xlf @@ -404,7 +404,7 @@ The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. - Nazwa pliku jest za długa. Powinna mieć {{ filename_max_length }} znak lub mniej.|Nazwa pliku jest za długa. Powinna mieć {{ filename_max_length }} znaków lub mniej. + Nazwa pliku jest za długa. Powinna mieć {{ filename_max_length }} znak lub mniej.|Nazwa pliku jest za długa. Powinna mieć {{ filename_max_length }} znaki lub mniej.|Nazwa pliku jest za długa. Powinna mieć {{ filename_max_length }} znaków lub mniej. The password strength is too low. Please use a stronger password. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf index ba7178f672ef7..7d044b8fc3ace 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.sq.xlf @@ -449,7 +449,7 @@ This URL is missing a top-level domain. - Kësaj URL i mungon një domain i nivelit të lartë. + Kësaj URL-je i mungon një domain i nivelit të sipërm. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. @@ -477,7 +477,7 @@ This value is not a valid Twig template. - Kjo vlerë nuk është një shabllon Twig i vlefshëm. + Kjo vlerë nuk është një shabllon Twig i vlefshëm. diff --git a/src/Symfony/Component/Validator/Test/CompoundConstraintTestCase.php b/src/Symfony/Component/Validator/Test/CompoundConstraintTestCase.php index 1a0544c82e7e6..2282645f23ffc 100644 --- a/src/Symfony/Component/Validator/Test/CompoundConstraintTestCase.php +++ b/src/Symfony/Component/Validator/Test/CompoundConstraintTestCase.php @@ -35,7 +35,7 @@ abstract class CompoundConstraintTestCase extends TestCase protected ValidatorInterface $validator; protected ?ConstraintViolationListInterface $violationList = null; protected ExecutionContextInterface $context; - protected string $root; + protected mixed $root; private mixed $validatedValue; diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AllTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AllTest.php index c91f06875e36d..08c303f81e712 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AllTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AllTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Validator\Constraints\All; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @author Bernhard Schussek @@ -36,4 +37,20 @@ public function testRejectValidConstraint() new Valid(), ]); } + + public function testMissingConstraints() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', All::class)); + + new All(null); + } + + public function testMissingConstraintsDoctrineStyle() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', All::class)); + + new All([]); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfTest.php index 66b8168dfbb6b..25e1878f4b5cb 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AtLeastOneOfTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Validator\Constraints\AtLeastOneOf; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @author Przemysław Bogusz @@ -36,4 +37,20 @@ public function testRejectValidConstraint() new Valid(), ]); } + + public function testMissingConstraints() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', AtLeastOneOf::class)); + + new AtLeastOneOf(null); + } + + public function testMissingConstraintsDoctrineStyle() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', AtLeastOneOf::class)); + + new AtLeastOneOf([]); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php index af0781b6556b9..a50930b9b6e60 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CardSchemeTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\CardScheme; +use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -37,6 +38,14 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + public function testMissingSchemes() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "schemes" must be set for constraint "%s".', CardScheme::class)); + + new CardScheme(null); + } } class CardSchemeDummy diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php index 4299edb2640cd..c1c32f90ab2fe 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CollectionTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\InvalidOptionsException; +use Symfony\Component\Validator\Exception\MissingOptionsException; /** * @author Bernhard Schussek @@ -207,4 +208,12 @@ public function testEmptyConstraintListForFieldInOptions(?array $fieldConstraint $this->assertTrue($constraint->allowExtraFields); $this->assertSame('foo bar baz', $constraint->extraFieldsMessage); } + + public function testMissingFields() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "fields" must be set for constraint "%s".', Collection::class)); + + new Collection(null); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CssColorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CssColorTest.php index 09938760bf54b..e1e3e250114f8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CssColorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CssColorTest.php @@ -40,6 +40,26 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + public function testMissingPatternDoctrineStyle() + { + $constraint = new CssColor([]); + + $this->assertSame([ + CssColor::HEX_LONG, + CssColor::HEX_LONG_WITH_ALPHA, + CssColor::HEX_SHORT, + CssColor::HEX_SHORT_WITH_ALPHA, + CssColor::BASIC_NAMED_COLORS, + CssColor::EXTENDED_NAMED_COLORS, + CssColor::SYSTEM_COLORS, + CssColor::KEYWORDS, + CssColor::RGB, + CssColor::RGBA, + CssColor::HSL, + CssColor::HSLA, + ], $constraint->formats); + } } class CssColorDummy diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php index 89db330b99c55..07abb071dbff1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ExpressionTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Expression; +use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -41,6 +42,25 @@ public function testAttributes() self::assertSame('some attached data', $cConstraint->payload); self::assertFalse($cConstraint->negate); } + + public function testMissingPattern() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "expression" must be set for constraint "%s".', Expression::class)); + + new Expression(null); + } + + /** + * @group legacy + */ + public function testMissingPatternDoctrineStyle() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "expression" must be set for constraint "%s".', Expression::class)); + + new Expression([]); + } } class ExpressionDummy diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php index f9393158d5d39..3ae3864d5a355 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IsbnValidatorTest.php @@ -121,7 +121,7 @@ public static function getInvalidIsbn() public function testNullIsValid() { - $constraint = new Isbn(true); + $constraint = new Isbn(); $this->validator->validate(null, $constraint); @@ -130,7 +130,7 @@ public function testNullIsValid() public function testEmptyStringIsValid() { - $constraint = new Isbn(true); + $constraint = new Isbn(); $this->validator->validate('', $constraint); @@ -140,7 +140,7 @@ public function testEmptyStringIsValid() public function testExpectsStringCompatibleType() { $this->expectException(UnexpectedValueException::class); - $constraint = new Isbn(true); + $constraint = new Isbn(); $this->validator->validate(new \stdClass(), $constraint); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php index 5a060e4dab0c4..3b38195124d92 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LocaleValidatorTest.php @@ -97,7 +97,7 @@ public function testTooLongLocale() $this->validator->validate($locale, $constraint); $this->buildViolation('myMessage') - ->setParameter('{{ value }}', '"' . $locale . '"') + ->setParameter('{{ value }}', '"'.$locale.'"') ->setCode(Locale::NO_SUCH_LOCALE_ERROR) ->assertRaised(); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php index 96b5d5fc4386d..853e0d78504aa 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RegexTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Regex; use Symfony\Component\Validator\Exception\InvalidArgumentException; +use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -138,6 +139,25 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + public function testMissingPattern() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "pattern" must be set for constraint "%s".', Regex::class)); + + new Regex(null); + } + + /** + * @group legacy + */ + public function testMissingPatternDoctrineStyle() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "pattern" must be set for constraint "%s".', Regex::class)); + + new Regex([]); + } } class RegexDummy diff --git a/src/Symfony/Component/Validator/Tests/Constraints/SequentiallyTest.php b/src/Symfony/Component/Validator/Tests/Constraints/SequentiallyTest.php index 62b23513f1810..87aa9b46cd17b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/SequentiallyTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/SequentiallyTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Validator\Constraints\Sequentially; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\MissingOptionsException; class SequentiallyTest extends TestCase { @@ -35,4 +36,20 @@ public function testRejectValidConstraint() new Valid(), ]); } + + public function testMissingConstraints() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', Sequentially::class)); + + new Sequentially(null); + } + + public function testMissingConstraintsDoctrineStyle() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "constraints" must be set for constraint "%s".', Sequentially::class)); + + new Sequentially([]); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php b/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php index 2c018cdbf3d1f..73acddd4314d5 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/TypeTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Validator\Constraints\Type; +use Symfony\Component\Validator\Exception\MissingOptionsException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -36,6 +37,14 @@ public function testAttributes() self::assertSame(['my_group'], $cConstraint->groups); self::assertSame('some attached data', $cConstraint->payload); } + + public function testMissingType() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage(\sprintf('The options "type" must be set for constraint "%s".', Type::class)); + + new Type(null); + } } class TypeDummy diff --git a/src/Symfony/Component/Validator/Tests/Constraints/WhenTest.php b/src/Symfony/Component/Validator/Tests/Constraints/WhenTest.php index 8f04376b337a2..6f82c6429c135 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/WhenTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/WhenTest.php @@ -37,6 +37,14 @@ public function testMissingOptionsExceptionIsThrown() new When([]); } + public function testMissingConstraints() + { + $this->expectException(MissingOptionsException::class); + $this->expectExceptionMessage('The options "constraints" must be set for constraint "Symfony\Component\Validator\Constraints\When".'); + + new When('true'); + } + public function testNonConstraintsAreRejected() { $this->expectException(ConstraintDefinitionException::class); diff --git a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php index 91449f72e1939..1ae14ba30fd56 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/RecursiveValidatorTest.php @@ -120,7 +120,7 @@ public function testValidate() $violations = $this->validate('Bernhard', $constraint, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -156,7 +156,7 @@ public function testClassConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -195,7 +195,7 @@ public function testPropertyConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -234,7 +234,7 @@ public function testGetterConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -271,7 +271,7 @@ public function testArray() $violations = $this->validate($array, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -308,7 +308,7 @@ public function testRecursiveArray() $violations = $this->validate($array, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -345,7 +345,7 @@ public function testTraversable() $violations = $this->validate($traversable, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -384,7 +384,7 @@ public function testRecursiveTraversable() $violations = $this->validate($traversable, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -422,7 +422,7 @@ public function testReferenceClassConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -463,7 +463,7 @@ public function testReferencePropertyConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -504,7 +504,7 @@ public function testReferenceGetterConstraint() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -525,7 +525,7 @@ public function testsIgnoreNullReference() $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -570,7 +570,7 @@ public function testArrayReference($constraintMethod) $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -611,7 +611,7 @@ public function testRecursiveArrayReference($constraintMethod) $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -643,7 +643,7 @@ public function testOnlyCascadedArraysAreTraversed() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -666,7 +666,7 @@ public function testArrayTraversalCannotBeDisabled($constraintMethod) $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -690,7 +690,7 @@ public function testRecursiveArrayTraversalCannotBeDisabled($constraintMethod) $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -706,7 +706,7 @@ public function testIgnoreScalarsDuringArrayTraversal($constraintMethod) $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -722,7 +722,7 @@ public function testIgnoreNullDuringArrayTraversal($constraintMethod) $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -752,7 +752,7 @@ public function testTraversableReference() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -781,7 +781,7 @@ public function testDisableTraversableTraversal() $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -829,7 +829,7 @@ public function testEnableRecursiveTraversableTraversal() $violations = $this->validate($entity, null, 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -877,7 +877,7 @@ public function testValidateProperty() $violations = $this->validateProperty($entity, 'firstName', 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -940,7 +940,7 @@ public function testValidatePropertyValue() 'Group' ); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -989,7 +989,7 @@ public function testValidatePropertyValueWithClassName() 'Group' ); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1028,7 +1028,7 @@ public function testValidateObjectOnlyOncePerGroup() $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1048,7 +1048,7 @@ public function testValidateDifferentObjectsSeparately() $violations = $this->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(2, $violations); } @@ -1071,7 +1071,7 @@ public function testValidateSingleGroup() $violations = $this->validate($entity, null, 'Group 2'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1094,7 +1094,7 @@ public function testValidateMultipleGroups() $violations = $this->validate($entity, null, ['Group 1', 'Group 2']); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(2, $violations); } @@ -1127,7 +1127,7 @@ public function testReplaceDefaultGroupByGroupSequenceObject() $violations = $this->validate($entity, null, 'Default'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); } @@ -1161,7 +1161,7 @@ public function testReplaceDefaultGroupByGroupSequenceArray() $violations = $this->validate($entity, null, 'Default'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Group 2', $violations[0]->getMessage()); } @@ -1193,7 +1193,7 @@ public function testPropagateDefaultGroupToReferenceWhenReplacingDefaultGroup() $violations = $this->validate($entity, null, 'Default'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in Default group', $violations[0]->getMessage()); } @@ -1223,7 +1223,7 @@ public function testValidateCustomGroupWhenDefaultGroupWasReplaced() $violations = $this->validate($entity, null, 'Other Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Violation in other group', $violations[0]->getMessage()); } @@ -1261,7 +1261,7 @@ public function testReplaceDefaultGroup($sequence, array $assertViolations) $violations = $this->validate($entity, null, 'Default'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(\count($assertViolations), $violations); foreach ($assertViolations as $key => $message) { $this->assertSame($message, $violations[$key]->getMessage()); @@ -1364,7 +1364,7 @@ public function testGroupSequenceAbortsAfterFailedGroup() $sequence = new GroupSequence(['Group 1', 'Group 2', 'Group 3']); $violations = $this->validator->validate($entity, new Valid(), $sequence); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message 1', $violations[0]->getMessage()); } @@ -1394,7 +1394,7 @@ public function testGroupSequenceIncludesReferences() $sequence = new GroupSequence(['Group 1', 'Entity']); $violations = $this->validator->validate($entity, new Valid(), $sequence); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Reference violation 1', $violations[0]->getMessage()); } @@ -1412,7 +1412,7 @@ public function testValidateInSeparateContext() ->validate($value->reference, new Valid(), 'Group') ; - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1453,7 +1453,7 @@ public function testValidateInSeparateContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Separate violation', $violations[0]->getMessage()); } @@ -1509,7 +1509,7 @@ public function testValidateInContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1572,7 +1572,7 @@ public function testValidateArrayInContext() $violations = $this->validator->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1610,7 +1610,7 @@ public function testTraverseTraversableByDefault() $violations = $this->validate($traversable, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1642,7 +1642,7 @@ public function testTraversalEnabledOnClass() $violations = $this->validate($traversable, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1666,7 +1666,7 @@ public function testTraversalDisabledOnClass() $violations = $this->validate($traversable, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1700,7 +1700,7 @@ public function testReferenceTraversalDisabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1727,7 +1727,7 @@ public function testReferenceTraversalEnabledOnReferenceDisabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1754,7 +1754,7 @@ public function testReferenceTraversalDisabledOnReferenceEnabledOnClass() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1774,7 +1774,7 @@ public function testReferenceCascadeDisabledByDefault() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1796,7 +1796,7 @@ public function testReferenceCascadeEnabledIgnoresUntyped() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(0, $violations); } @@ -1826,7 +1826,7 @@ public function testTypedReferenceCascadeEnabled() $violations = $this->validate($entity, new Valid(), 'Group'); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertInstanceOf(Callback::class, $violations->get(0)->getConstraint()); } @@ -1848,7 +1848,7 @@ public function testAddCustomizedViolation() $violations = $this->validator->validate($entity); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); $this->assertSame('Message value', $violations[0]->getMessage()); $this->assertSame('Message %param%', $violations[0]->getMessageTemplate()); @@ -1875,7 +1875,7 @@ public function testNoDuplicateValidationIfClassConstraintInMultipleGroups() $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } @@ -1894,7 +1894,7 @@ public function testNoDuplicateValidationIfPropertyConstraintInMultipleGroups() $violations = $this->validator->validate($entity, new Valid(), ['Group 1', 'Group 2']); - /* @var ConstraintViolationInterface[] $violations */ + /** @var ConstraintViolationInterface[] $violations */ $this->assertCount(1, $violations); } diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index c8a26d0b8533f..9805bdcd4e0b3 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -443,7 +443,7 @@ private function validateClassNode(object $object, ?string $cacheKey, ClassMetad } else { // The group sequence is dynamically obtained from the validated // object - /* @var \Symfony\Component\Validator\GroupSequenceProviderInterface $object */ + /** @var \Symfony\Component\Validator\GroupSequenceProviderInterface $object */ $group = $object->getGroupSequence(); } $defaultOverridden = true; diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 0eaac5f6bf735..368373f53c051 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -40,7 +40,7 @@ "symfony/property-info": "^6.4|^7.0", "symfony/string": "^6.4|^7.0", "symfony/translation": "^6.4.3|^7.0.3", - "symfony/type-info": "^7.1", + "symfony/type-info": "^7.1.8", "egulias/email-validator": "^2.1.10|^3|^4" }, "conflict": { diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index c7a4c8c3b08dd..593a2c69a0b46 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -185,17 +185,48 @@ protected function utf8Encode(?string $s): ?string return $s; } - if (!\function_exists('iconv')) { - throw new \RuntimeException('Unable to convert a non-UTF-8 string to UTF-8: required function iconv() does not exist. You should install ext-iconv or symfony/polyfill-iconv.'); + if (\function_exists('iconv')) { + if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { + return $c; + } + if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { + return $c; + } } - if (false !== $c = @iconv($this->charset, 'UTF-8', $s)) { - return $c; + $s .= $s; + $len = \strlen($s); + $mapCp1252 = false; + + for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { + if ($s[$i] < "\x80") { + $s[$j] = $s[$i]; + } elseif ($s[$i] < "\xC0") { + $s[$j] = "\xC2"; + $s[++$j] = $s[$i]; + if ($s[$i] < "\xA0") { + $mapCp1252 = true; + } + } else { + $s[$j] = "\xC3"; + $s[++$j] = \chr(\ord($s[$i]) - 64); + } } - if ('CP1252' !== $this->charset && false !== $c = @iconv('CP1252', 'UTF-8', $s)) { - return $c; + + $s = substr($s, 0, $j); + + if (!$mapCp1252) { + return $s; } - return iconv('CP850', 'UTF-8', $s); + return strtr($s, [ + "\xC2\x80" => '€', "\xC2\x82" => '‚', "\xC2\x83" => 'ƒ', "\xC2\x84" => '„', + "\xC2\x85" => '…', "\xC2\x86" => '†', "\xC2\x87" => '‡', "\xC2\x88" => 'ˆ', + "\xC2\x89" => '‰', "\xC2\x8A" => 'Š', "\xC2\x8B" => '‹', "\xC2\x8C" => 'Œ', + "\xC2\x8D" => 'Ž', "\xC2\x91" => '‘', "\xC2\x92" => '’', "\xC2\x93" => '“', + "\xC2\x94" => '”', "\xC2\x95" => '•', "\xC2\x96" => '–', "\xC2\x97" => '—', + "\xC2\x98" => '˜', "\xC2\x99" => '™', "\xC2\x9A" => 'š', "\xC2\x9B" => '›', + "\xC2\x9C" => 'œ', "\xC2\x9E" => 'ž', + ]); } } diff --git a/src/Symfony/Component/VarDumper/Dumper/ContextProvider/CliContextProvider.php b/src/Symfony/Component/VarDumper/Dumper/ContextProvider/CliContextProvider.php index 38f878971c53f..292b1a410343d 100644 --- a/src/Symfony/Component/VarDumper/Dumper/ContextProvider/CliContextProvider.php +++ b/src/Symfony/Component/VarDumper/Dumper/ContextProvider/CliContextProvider.php @@ -26,7 +26,7 @@ public function getContext(): ?array return [ 'command_line' => $commandLine = implode(' ', $_SERVER['argv'] ?? []), - 'identifier' => hash('crc32b', $commandLine.$_SERVER['REQUEST_TIME_FLOAT']), + 'identifier' => hash('xxh128', $commandLine.'@'.$_SERVER['REQUEST_TIME_FLOAT']), ]; } } diff --git a/src/Symfony/Component/VarDumper/Dumper/ContextProvider/RequestContextProvider.php b/src/Symfony/Component/VarDumper/Dumper/ContextProvider/RequestContextProvider.php index deef2524164e8..e3ee48737b6ff 100644 --- a/src/Symfony/Component/VarDumper/Dumper/ContextProvider/RequestContextProvider.php +++ b/src/Symfony/Component/VarDumper/Dumper/ContextProvider/RequestContextProvider.php @@ -44,7 +44,7 @@ public function getContext(): ?array 'uri' => $request->getUri(), 'method' => $request->getMethod(), 'controller' => $controller ? $this->cloner->cloneVar($controller) : $controller, - 'identifier' => spl_object_hash($request), + 'identifier' => hash('xxh128', spl_object_id($request).'@'.$_SERVER['REQUEST_TIME_FLOAT']), ]; } } diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index ed312c5288b88..d11e55924ca2c 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -21,7 +21,6 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "ext-iconv": "*", "symfony/console": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/process": "^6.4|^7.0", diff --git a/src/Symfony/Component/VarExporter/ProxyHelper.php b/src/Symfony/Component/VarExporter/ProxyHelper.php index b815e7040c501..315d3dcf98140 100644 --- a/src/Symfony/Component/VarExporter/ProxyHelper.php +++ b/src/Symfony/Component/VarExporter/ProxyHelper.php @@ -633,7 +633,9 @@ public static function exportType(\ReflectionFunctionAbstract|\ReflectionPropert return ''; } if (null === $glue) { - return (!$noBuiltin && $type->allowsNull() && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0]; + $defaultNull = $owner instanceof \ReflectionParameter && 'NULL' === rtrim(substr(explode('$'.$owner->name.' = ', (string) $owner, 2)[1] ?? '', 0, -2)); + + return (!$noBuiltin && ($type->allowsNull() || $defaultNull) && !\in_array($name, ['mixed', 'null'], true) ? '?' : '').$types[0]; } sort($types); diff --git a/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php b/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php index c650626847055..2060e35dc41dd 100644 --- a/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php +++ b/src/Symfony/Component/VarExporter/Tests/LegacyLazyGhostTraitTest.php @@ -334,7 +334,7 @@ public function testPropertyHooksWithDefaultValue() $this->assertSame(321, $object->backedIntWithDefault); $this->assertSame('321', $object->backedStringWithDefault); - $this->assertSame(false, $object->backedBoolWithDefault); + $this->assertFalse($object->backedBoolWithDefault); $this->assertTrue($initialized); $initialized = false; @@ -347,7 +347,7 @@ public function testPropertyHooksWithDefaultValue() $this->assertTrue($initialized); $this->assertSame(654, $object->backedIntWithDefault); $this->assertSame('654', $object->backedStringWithDefault); - $this->assertSame(true, $object->backedBoolWithDefault); + $this->assertTrue($object->backedBoolWithDefault); } /** diff --git a/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php b/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php index 0cb7e2017b957..6ce732b1c4e05 100644 --- a/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php +++ b/src/Symfony/Component/Workflow/DataCollector/WorkflowDataCollector.php @@ -101,7 +101,7 @@ public function buildMermaidLiveLink(string $name): string 'autoSync' => false, ]; - $compressed = zlib_encode(json_encode($payload), ZLIB_ENCODING_DEFLATE); + $compressed = zlib_encode(json_encode($payload), \ZLIB_ENCODING_DEFLATE); $suffix = rtrim(strtr(base64_encode($compressed), '+/', '-_'), '='); diff --git a/src/Symfony/Component/Workflow/DependencyInjection/WorkflowValidatorPass.php b/src/Symfony/Component/Workflow/DependencyInjection/WorkflowValidatorPass.php index 60072ef0ca612..d1e46226129b7 100644 --- a/src/Symfony/Component/Workflow/DependencyInjection/WorkflowValidatorPass.php +++ b/src/Symfony/Component/Workflow/DependencyInjection/WorkflowValidatorPass.php @@ -14,7 +14,6 @@ use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; /** * @author Grégoire Pineau diff --git a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php index 2aaf54932aae5..ad7b0c23d12fc 100644 --- a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php @@ -141,7 +141,7 @@ protected function findTransitions(Definition $definition, bool $withMetadata): /** * @internal */ - protected function addPlaces(array $places, float $withMetadata): string + protected function addPlaces(array $places, bool $withMetadata): string { $code = ''; @@ -303,7 +303,7 @@ protected function addAttributes(array $attributes): string * * @internal */ - protected function formatLabel(Definition $definition, string $withMetadata, array $options): string + protected function formatLabel(Definition $definition, bool $withMetadata, array $options): string { $currentLabel = $options['label'] ?? ''; diff --git a/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php b/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php index 3a29da6753672..a8d1978bac652 100644 --- a/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php +++ b/src/Symfony/Component/Workflow/Tests/Dumper/MermaidDumperTest.php @@ -104,7 +104,7 @@ public static function provideWorkflowDefinitionWithoutMarking(): iterable ."transition4-->place6\n" ."transition5[\"t6\"]\n" ."place5-->transition5\n" - ."transition5-->place6", + .'transition5-->place6', ]; yield [ self::createWorkflowWithSameNameTransition(), @@ -124,7 +124,7 @@ public static function provideWorkflowDefinitionWithoutMarking(): iterable ."transition2-->place0\n" ."transition3[\"to_a\"]\n" ."place2-->transition3\n" - ."transition3-->place0", + .'transition3-->place0', ]; yield [ self::createSimpleWorkflowDefinition(), @@ -140,7 +140,7 @@ public static function provideWorkflowDefinitionWithoutMarking(): iterable ."linkStyle 1 stroke:Grey\n" ."transition1[\"t2\"]\n" ."place1-->transition1\n" - ."transition1-->place2", + .'transition1-->place2', ]; } @@ -169,7 +169,7 @@ public static function provideWorkflowWithReservedWords(): iterable ."place1-->transition0\n" ."transition1[\"t1\"]\n" ."place2-->transition1\n" - ."transition1-->place3", + .'transition1-->place3', ]; } @@ -186,7 +186,7 @@ public static function provideStateMachine(): iterable ."place3-->|\"My custom transition label 3\"|place1\n" ."linkStyle 1 stroke:Grey\n" ."place1-->|\"t2\"|place2\n" - ."place1-->|\"t3\"|place3", + .'place1-->|"t3"|place3', ]; } @@ -212,7 +212,7 @@ public static function provideWorkflowWithMarking(): iterable ."linkStyle 1 stroke:Grey\n" ."transition1[\"t2\"]\n" ."place1-->transition1\n" - ."transition1-->place2", + .'transition1-->place2', ]; } } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 3a0889a5090b3..1c9fa609d0a25 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -243,7 +243,7 @@ private static function dumpArray(array $value, int $flags): string private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $flags): string { $output = []; - $keyFlags = $flags &~ Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES; + $keyFlags = $flags & ~Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES; foreach ($value as $key => $val) { if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) { $key = (string) $key; diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index e937336ca4858..8eac4aee0b54c 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -946,7 +946,7 @@ public static function getForceQuotesOnValuesData(): iterable ]; yield 'backslash' => [ - ['foo' => "back\\slash"], + ['foo' => 'back\\slash'], '{ foo: "back\\\\slash" }', ]; diff --git a/src/Symfony/Contracts/Service/ServiceSubscriberTrait.php b/src/Symfony/Contracts/Service/ServiceSubscriberTrait.php index ed4cec044a831..58ea7c5496486 100644 --- a/src/Symfony/Contracts/Service/ServiceSubscriberTrait.php +++ b/src/Symfony/Contracts/Service/ServiceSubscriberTrait.php @@ -53,7 +53,7 @@ public static function getSubscribedServices(): array throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class)); } - /* @var SubscribedService $attribute */ + /** @var SubscribedService $attribute */ $attribute = $attribute->newInstance(); $attribute->key ??= self::class.'::'.$method->name; $attribute->type ??= $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType; diff --git a/src/Symfony/Contracts/Translation/Test/TranslatorTest.php b/src/Symfony/Contracts/Translation/Test/TranslatorTest.php index da19d09bd0856..5342f5b82c341 100644 --- a/src/Symfony/Contracts/Translation/Test/TranslatorTest.php +++ b/src/Symfony/Contracts/Translation/Test/TranslatorTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\TranslatableMessage; use Symfony\Contracts\Translation\TranslatorInterface; use Symfony\Contracts\Translation\TranslatorTrait; @@ -124,10 +125,12 @@ public function testGetLocaleReturnsDefaultLocaleIfNotSet() public static function getTransTests() { - return [ - ['Symfony is great!', 'Symfony is great!', []], - ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']], - ]; + yield ['Symfony is great!', 'Symfony is great!', []]; + yield ['Symfony is awesome!', 'Symfony is %what%!', ['%what%' => 'awesome']]; + + if (class_exists(TranslatableMessage::class)) { + yield ['He said "Symfony is awesome!".', 'He said "%what%".', ['%what%' => new TranslatableMessage('Symfony is %what%!', ['%what%' => 'awesome'])]]; + } } public static function getTransChoiceTests() diff --git a/src/Symfony/Contracts/Translation/TranslatorTrait.php b/src/Symfony/Contracts/Translation/TranslatorTrait.php index 06210b0ed368d..afedd9928b39b 100644 --- a/src/Symfony/Contracts/Translation/TranslatorTrait.php +++ b/src/Symfony/Contracts/Translation/TranslatorTrait.php @@ -41,6 +41,12 @@ public function trans(?string $id, array $parameters = [], ?string $domain = nul return ''; } + foreach ($parameters as $k => $v) { + if ($v instanceof TranslatableInterface) { + $parameters[$k] = $v->trans($this, $locale); + } + } + if (!isset($parameters['%count%']) || !is_numeric($parameters['%count%'])) { return strtr($id, $parameters); } pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy