8000 Merge branch '4.3' into 4.4 · symfony/symfony@55c0b02 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 55c0b02

Browse files
Merge branch '4.3' into 4.4
* 4.3: (34 commits) [PhpunitBridge] Read environment variable from superglobals [Bridge/PhpUnit] Fix PHP5.5 compat [PhpUnitBridge] More accurate grouping fixed CS Extract unrecoverable exception to interface [FrameworkBundle] Fix calling Client::getProfile() before sending a request Fix type error [Security/Core] require libsodium >= 1.0.14 [Workflow] re-add workflow.definition tag to workflow services [Security/Core] Don't use ParagonIE_Sodium_Compat revert #30525 due to performance penalty collect called listeners information only once [Lock] fix missing inherit docs in RedisStore [Messenger] fix retrying handlers using DoctrineTransactionMiddleware [Mailgun Mailer] fixed issue when using html body [HttpClient] fix timing measurements with NativeHttpClient [HttpClient] fix dealing with 1xx informational responses add test to avoid regressions fix mirroring directory into parent directory fix typos ...
2 parents bd8ad3f + 2dedf38 commit 55c0b02

File tree

60 files changed

+609
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+609
-224
lines changed

src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,9 @@ private function sanitizeQuery($connectionName, $query)
138138
if (!\is_array($query['params'])) {
139139
$query['params'] = [$query['params']];
140140
}
141+
if (!\is_array($query['types'])) {
142+
$query['types'] = [];
143+
}
141144
foreach ($query['params'] as $j => $param) {
142145
if (isset($query['types'][$j])) {
143146
// Transform the param according to the type

src/Symfony/Bridge/Doctrine/Messenger/DoctrineTransactionMiddleware.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313

1414
use Doctrine\ORM\EntityManagerInterface;
1515
use Symfony\Component\Messenger\Envelope;
16+
use Symfony\Component\Messenger\Exception\HandlerFailedException;
1617
use Symfony\Component\Messenger\Middleware\StackInterface;
18+
use Symfony\Component\Messenger\Stamp\HandledStamp;
1719

1820
/**
1921
* Wraps all handlers in a single doctrine transaction.
@@ -36,6 +38,12 @@ protected function handleForManager(EntityManagerInterface $entityManager, Envel
3638
} catch (\Throwable $exception) {
3739
$entityManager->getConnection()->rollBack();
3840

41+
if ($exception instanceof HandlerFailedException) {
42+
// Remove all HandledStamp from the envelope so the retry will execute all handlers again.
43+
// When a handler fails, the queries of allegedly successful previous handlers just got rolled back.
44+
throw new HandlerFailedException($exception->getEnvelope()->withoutAll(HandledStamp::class), $exception->getNestedExceptions());
45+
}
46+
3947
throw $exception;
4048
}
4149
}

src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ public function testCollectQueryWithNoParams()
102102
$this->assertTrue($collectedQueries['default'][1]['explainable']);
103103
}
104104

105+
public function testCollectQueryWithNoTypes()
106+
{
107+
$queries = [
108+
['sql' => 'SET sql_mode=(SELECT REPLACE(@@sql_mode, \'ONLY_FULL_GROUP_BY\', \'\'))', 'params' => [], 'types' => null, 'executionMS' => 1],
109+
];
110+
$c = $this->createCollector($queries);
111+
$c->collect(new Request(), new Response());
112+
113+
$collectedQueries = $c->getQueries();
114+
$this->assertSame([], $collectedQueries['default'][0]['types']);
115+
}
116+
105117
public function testReset()
106118
{
107119
$queries = [

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,10 +139,13 @@ public function handleError($type, $msg, $file, $line, $context = [])
139139
$group = 'unsilenced';
140140
} elseif ($deprecation->isLegacy(self::$utilPrefix)) {
141141
$group = 'legacy';
142-
} elseif (!$deprecation->isSelf()) {
143-
$group = $deprecation->isIndirect() ? 'remaining indirect' : 'remaining direct';
144142
} else {
145-
$group = 'remaining self';
143+
$group = [
144+
Deprecation::TYPE_SELF => 'remaining self',
145+
Deprecation::TYPE_DIRECT => 'remaining direct',
146+
Deprecation::TYPE_INDIRECT => 'remaining indirect',
147+
Deprecation::TYPE_UNDETERMINED => 'other',
148+
][$deprecation->getType()];
146149
}
147150

148151
if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) {
@@ -216,7 +219,13 @@ private function getConfiguration()
216219
return $this->configuration;
217220
}
218221
if (false === $mode = $this->mode) {
219-
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
222+
if (isset($_SERVER['SYMFONY_DEPRECATIONS_HELPER'])) {
223+
$mode = $_SERVER['SYMFONY_DEPRECATIONS_HELPER'];
224+
} elseif (isset($_ENV['SYMFONY_DEPRECATIONS_HELPER'])) {
225+
$mode = $_ENV['SYMFONY_DEPRECATIONS_HELPER'];
226+
} else {
227+
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
228+
}
220229
}
221230
if ('strict' === $mode) {
222231
return $this->configuration = Configuration::inStrictMode();

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler/Deprecation.php

Lines changed: 70 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,15 @@
1818
*/
1919
class Deprecation
2020
{
21+
const PATH_TYPE_VENDOR = 'path_type_vendor';
22+
const PATH_TYPE_SELF = 'path_type_internal';
23+
const PATH_TYPE_UNDETERMINED = 'path_type_undetermined';
24+
25+
const TYPE_SELF = 'type_self';
26+
const TYPE_DIRECT = 'type_direct';
27+
const TYPE_INDIRECT = 'type_indirect';
28+
const TYPE_UNDETERMINED = 'type_undetermined';
29+
2130
/**
2231
* @var array
2332
*/
@@ -39,13 +48,21 @@ class Deprecation
3948
private $originMethod;
4049

4150
/**
42-
* @var bool
51+
* @var string one of the PATH_TYPE_* constants
4352
*/
44-
private $self;
53+
private $triggeringFilePathType;
4554

4655
/** @var string[] absolute paths to vendor directories */
4756
private static $vendors;
4857

58+
/**
59+
* @var string[] absolute paths to source or tests of the project. This
60+
* excludes cache directories, because it is based on
61+
* autoloading rules and cache systems typically do not use
62+
* those.
63+
*/
64+
private static $internalPaths;
65+
4966
/**
5067
* @param string $message
5168
* @param string $file
@@ -59,7 +76,7 @@ public function __construct($message, array $trace, $file)
5976
// No-op
6077
}
6178
$line = $trace[$i];
62-
$this->self = !$this->pathOriginatesFromVendor($file);
79+
$this->trigerringFilePathType = $this->getPathType($file);
6380
if (isset($line['object']) || isset($line['class'])) {
6481
if (isset($line['class']) && 0 === strpos($line['class'], SymfonyTestsListenerFor::class)) {
6582
$parsedMsg = unserialize($this->message);
@@ -70,8 +87,9 @@ public function __construct($message, array $trace, $file)
7087
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
7188
// then we need to use the serialized information to determine
7289
// if the error has been triggered from vendor code.
73-
$this->self = isset($parsedMsg['triggering_file'])
74-
&& $this->pathOriginatesFromVendor($parsedMsg['triggering_file']);
90+
if (isset($parsedMsg['triggering_file'])) {
91+
$this->trigerringFilePathType = $this->getPathType($parsedMsg['triggering_file']);
92+
}
7593

7694
return;
7795
}
@@ -101,14 +119,6 @@ public function originatesFromAnObject()
101119
return isset($this->originClass);
102120
}
103121

104-
/**
105-
* @return bool
106-
*/
107-
public function isSelf()
108-
{
109-
return $this->self;
110-
}
111-
112122
/**
113123
* @return string
114124
*/
@@ -163,10 +173,16 @@ public function isLegacy($utilPrefix)
163173
* Tells whether both the calling package and the called package are vendor
164174
* packages.
165175
*
166-
* @return bool
176+
* @return string
167177
*/
168-
public function isIndirect()
178+
public function getType()
169179
{
180+
if (self::PATH_TYPE_SELF === $this->trigerringFilePathType) {
181+
return self::TYPE_SELF;
182+
}
183+
if (self::PATH_TYPE_UNDETERMINED === $this->trigerringFilePathType) {
184+
return self::TYPE_UNDETERMINED;
185+
}
170186
$erroringFile = $erroringPackage = null;
171187
foreach ($this->trace as $line) {
172188
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
@@ -179,25 +195,28 @@ public function isIndirect()
179195
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
180196
continue;
181197
}
182-
if (!$this->pathOriginatesFromVendor($file)) {
183-
return false;
198+
if (self::PATH_TYPE_SELF === $this->getPathType($file)) {
199+
return self::TYPE_DIRECT;
200+
}
201+
if (self::PATH_TYPE_UNDETERMINED === $this->getPathType($file)) {
202+
return self::TYPE_UNDETERMINED;
184203
}
185204
if (null !== $erroringFile && null !== $erroringPackage) {
186205
$package = $this->getPackage($file);
187206
if ('composer' !== $package && $package !== $erroringPackage) {
188-
return true;
207+
return self::TYPE_INDIRECT;
189208
}
190209
continue;
191210
}
192211
$erroringFile = $file;
193212
$erroringPackage = $this->getPackage($file);
194213
}
195214

196-
return false;
215+
return self::TYPE_DIRECT;
197216
}
198217

199218
/**
200-
* pathOriginatesFromVendor() should always be called prior to calling this method.
219+
* getPathType() should always be called prior to calling this method.
201220
*
202221
* @param string $path
203222
*
@@ -237,6 +256,15 @@ private static function getVendors()
237256
$v = \dirname(\dirname($r->getFileName()));
238257
if (file_exists($v.'/composer/installed.json')) {
239258
self::$vendors[] = $v;
259+
$loader = require $v.'/autoload.php';
260+
$paths = self::getSourcePathsFromPrefixes(array_merge($loader->getPrefixes(), $loader->getPrefixesPsr4()));
261+
}
262+
}
263+
}
264+
foreach ($paths as $path) {
265+
foreach (self::$vendors as $vendor) {
266+
if (0 !== strpos($path, $vendor)) {
267+
self::$internalPaths[] = $path;
240268
}
241269
}
242270
}
@@ -245,24 +273,41 @@ private static function getVendors()
245273
return self::$vendors;
246274
}
247275

276+
private static function getSourcePathsFromPrefixes(array $prefixesByNamespace)
277+
{
278+
foreach ($prefixesByNamespace as $prefixes) {
279+
foreach ($prefixes as $prefix) {
280+
if (false !== realpath($prefix)) {
281+
yield realpath($prefix);
282+
}
283+
}
284+
}
285+
}
286+
248287
/**
249288
* @param string $path
250289
*
251-
* @return bool
290+
* @return string
252291
*/
253-
private function pathOriginatesFromVendor($path)
292+
private function getPathType($path)
254293
{
255294
$realPath = realpath($path);
256295
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
257-
return true;
296+
return self::PATH_TYPE_UNDETERMINED;
258297
}
259298
foreach (self::getVendors() as $vendor) {
260299
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
261-
return true;
300+
return self::PATH_TYPE_VENDOR;
262301
}
263302
}
264303

265-
return false;
304+
foreach (self::$internalPaths as $internalPath) {
305+
if (0 === strpos($realPath, $internalPath)) {
306+
return self::PATH_TYPE_SELF;
307+
}
308+
}
309+
310+
return self::PATH_TYPE_UNDETERMINED;
266311
}
267312

268313
/**
@@ -281,19 +326,4 @@ public function toString()
281326
"\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $exception->getTraceAsString()).
282327
"\n";
283328
}
284-
285-
private function getPackageFromLine(array $line)
286-
{
287-
if (!isset($line['file'])) {
288-
return 'internal function';
289-
}
290-
i 10000 f (!$this->pathOriginatesFromVendor($line['file'])) {
291-
return 'source code';
292-
}
293-
try {
294-
return $this->getPackage($line['file']);
295-
} catch (\RuntimeException $e) {
296-
return 'unknown';
297-
}
298-
}
299329
}

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/DeprecationTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function testItCanDetermineTheClassWhereTheDeprecationHappened()
2727
public function testItCanTellWhetherItIsInternal()
2828
{
2929
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
30-
$this->assertTrue($deprecation->isSelf());
30+
$this->assertSame(Deprecation::TYPE_SELF, $deprecation->getType());
3131
}
3232

3333
public function testLegacyTestMethodIsDetectedAsSuch()
@@ -46,7 +46,7 @@ public function testItCanBeConvertedToAString()
4646
public function testItRulesOutFilesOutsideVendorsAsIndirect()
4747
{
4848
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
49-
$this->assertFalse($deprecation->isIndirect());
49+
$this->assertNotSame(Deprecation::TYPE_INDIRECT, $deprecation->getType());
5050
}
5151

5252
/**

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,13 @@ Unsilenced deprecation notices (3)
7373
1x: unsilenced bar deprecation
7474
1x in FooTestCase::testNonLegacyBar
7575

76-
Remaining self deprecation notices (1)
77-
78-
1x: silenced bar deprecation
79-
1x in FooTestCase::testNonLegacyBar
80-
8176
Legacy deprecation notices (1)
8277

83-
Other deprecation notices (1)
78+
Other deprecation notices (2)
8479

8580
1x: root deprecation
8681

82+
1x: silenced bar deprecation
83+
1x in FooTestCase::testNonLegacyBar
84+
8785
I get precedence over any exit statements inside the deprecation error handler.

src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/disabled.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
--TEST--
2-
Test DeprecationErrorHandler in weak mode
2+
Test DeprecationErrorHandler in disabled mode
33
--FILE--
44
<?php
55

6-
putenv('SYMFONY_DEPRECATIONS_HELPER=disabled');
6+
$_SERVER['SYMFONY_DEPRECATIONS_HELPER'] = 'disabled';
77
putenv('ANSICON');
88
putenv('ConEmuANSI');
99
putenv('TERM');
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Test DeprecationErrorHandler in disabled mode (via putenv)
3+
--FILE--
4+
<?php
5+
6+
$_ENV['SYMFONY_DEPRECATIONS_HELPER'] = 'disabled';
7+
putenv('ANSICON');
8+
putenv('ConEmuANSI');
9+
putenv('TERM');
10+
11+
$vendor = __DIR__;
12+
while (!file_exists($vendor.'/vendor')) {
13+
$vendor = dirname($vendor);
14+
}
15+
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
16+
require PHPUNIT_COMPOSER_INSTALL;
17+
require_once __DIR__.'/../../bootstrap.php';
18+
19+
echo (int) set_error_handler('var_dump');
20+
echo (int) class_exists('Symfony\Bridge\PhpUnit\DeprecationErrorHandler', false);
21+
22+
?>
23+
--EXPECTF--
24+
00
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Test DeprecationErrorHandler in disabled mode (via putenv)
3+
--FILE--
4+
<?php
5+
6+
putenv('SYMFONY_DEPRECATIONS_HELPER=disabled');
7+
putenv('ANSICON');
8+
putenv('ConEmuANSI');
9+
putenv('TERM');
10+
11+
$vendor = __DIR__;
12+
while (!file_exists($vendor.'/vendor')) {
13+
$vendor = dirname($vendor);
14+
}
15+
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
16+
require PHPUNIT_COMPOSER_INSTALL;
17+
require_once __DIR__.'/../../bootstrap.php';
18+
19+
echo (int) set_error_handler('var_dump');
20+
echo (int) class_exists('Symfony\Bridge\PhpUnit\DeprecationErrorHandler', false);
21+
22+
?>
23+
--EXPECTF--
24+
00

0 commit comments

Comments
 (0)
0