Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 77639e2

Browse files
Merge branch '3.4'
* 3.4: [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord bumped Symfony version to 3.3.3 updated VERSION for 3.3.2 updated CHANGELOG for 3.3.2 [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables
2 parents 6f8430e + 25f1368 commit 77639e2

File tree

12 files changed

+342
-47
lines changed

12 files changed

+342
-47
lines changed

CHANGELOG-3.3.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ in 3.3 minor versions.
77
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
88
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1
99

10+
* 3.3.2 (2017-06-06)
11+
12+
* bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi)
13+
* bug #23063 [Cache] Fix extensibility of TagAwareAdapter::TAGS_PREFIX (wucdbm)
14+
* bug #22936 [Form] Mix attr option between guessed options and user options (yceruto)
15+
* bug #22976 [DependencyInjection] Use more clear message when unused environment variables detected (voronkovich)
16+
1017
* 3.3.1 (2017-06-05)
1118

1219
* bug #23067 [HttpFoundation][FrameworkBundle] Revert "trusted proxies" BC break (nicolas-grekas)

src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,15 @@ public function handle(array $record)
5151
if (!$this->socket = $this->socket ?: $this->createSocket()) {
5252
return false === $this->bubble;
5353
}
54+
} finally {
55+
restore_error_handler();
56+
}
5457

55-
$recordFormatted = $this->formatRecord($record);
58+
$recordFormatted = $this->formatRecord($record);
5659

60+
set_error_handler(self::class.'::nullErrorHandler');
61+
62+
try {
5763
if (-1 === stream_socket_sendto($this->socket, $recordFormatted)) {
5864
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
5965

src/Symfony/Component/Debug/ErrorHandler.php

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ class ErrorHandler
100100
private static $stackedErrors = array();
101101
private static $stackedErrorLevels = array();
102102
private static $toStringException = null;
103+
private static $silencedErrorCache = array();
104+
private static $silencedErrorCount = 0;
103105
private static $exitCode = 0;
104106

105107
/**
@@ -407,7 +409,24 @@ public function handleError($type, $message, $file, $line)
407409
$errorAsException = self::$toStringException;
408410
self::$toStringException = null;
409411
} elseif (!$throw && !($type & $level)) {
410-
$errorAsException = new SilencedErrorContext($type, $file, $line);
412+
if (isset(self::$silencedErrorCache[$message])) {
413+
$lightTrace = null;
414+
$errorAsException = self::$silencedErrorCache[$message];
415+
++$errorAsException->count;
416+
} else {
417+
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), $type, $file, $line, false) : array();
418+
$errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
419+
}
420+
421+
if (100 < ++self::$silencedErrorCount) {
422+
self::$silencedErrorCache = $lightTrace = array();
423+
self::$silencedErrorCount = 1;
424+
}
425+
self::$silencedErrorCache[$message] = $errorAsException;
426+
427+
if (null === $lightTrace) {
428+
return;
429+
}
411430
} else {
412431
if ($scope) {
413432
$errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context);
@@ -418,19 +437,7 @@ public function handleError($type, $message, $file, $line)
418437
// Clean the trace by removing function arguments and the first frames added by the error handler itself.
419438
if ($throw || $this->tracedErrors & $type) {
420439
$backtrace = $backtrace ?: $errorAsException->getTrace();
421-
$lightTrace = $backtrace;
422-
423-
for ($i = 0; isset($backtrace[$i]); ++$i) {
424-
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
425-
$lightTrace = array_slice($lightTrace, 1 + $i);
426-
break;
427-
}
428-
}
429-
if (!($throw || $this->scopedErrors & $type)) {
430-
for ($i = 0; isset($lightTrace[$i]); ++$i) {
431-
unset($lightTrace[$i]['args']);
432-
}
433-
}
440+
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
434441
$this->traceReflector->setValue($errorAsException, $lightTrace);
435442
} else {
436443
$this->traceReflector->setValue($errorAsException, array());
@@ -683,4 +690,23 @@ protected function getFatalErrorHandlers()
683690
new ClassNotFoundFatalErrorHandler(),
684691
);
685692
}
693+
694+
private function cleanTrace($backtrace, $type, $file, $line, $throw)
695+
{
696+
$lightTrace = $backtrace;
697+
698+
for ($i = 0; isset($backtrace[$i]); ++$i) {
699+
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
700+
$lightTrace = array_slice($lightTrace, 1 + $i);
701+
break;
702+
}
703+
}
704+
if (!($throw || $this->scopedErrors & $type)) {
705+
for ($i = 0; isset($lightTrace[$i]); ++$i) {
706+
unset($lightTrace[$i]['args']);
707+
}
708+
}
709+
710+
return $lightTrace;
711+
}
686712
}

src/Symfony/Component/Debug/Exception/SilencedErrorContext.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,20 @@
1818
*/
1919
class SilencedErrorContext implements \JsonSerializable
2020
{
21+
public $count = 1;
22+
2123
private $severity;
2224
private $file;
2325
private $line;
26+
private $trace;
2427

25-
public function __construct($severity, $file, $line)
28+
public function __construct($severity, $file, $line, array $trace = array(), $count = 1)
2629
{
2730
$this->severity = $severity;
2831
$this->file = $file;
2932
$this->line = $line;
33+
$this->trace = $trace;
34+
$this->count = $count;
3035
}
3136

3237
public function getSeverity()
@@ -44,12 +49,19 @@ public function getLine()
4449
return $this->line;
4550
}
4651

52+
public function getTrace()
53+
{
54+
return $this->trace;
55+
}
56+
4757
public function JsonSerialize()
4858
{
4959
return array(
5060
'severity' => $this->severity,
5161
'file' => $this->file,
5262
'line' => $this->line,
63+
'trace' => $this->trace,
64+
'count' => $this->count,
5365
);
5466
}
5567
}

src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,12 +221,17 @@ public function testHandleError()
221221

222222
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
223223

224-
$logArgCheck = function ($level, $message, $context) {
224+
$line = null;
225+
$logArgCheck = function ($level, $message, $context) use (&$line) {
225226
$this->assertEquals('Notice: Undefined variable: undefVar', $message);
226227
$this->assertArrayHasKey('exception', $context);
227228
$exception = $context['exception'];
228229
$this->assertInstanceOf(SilencedErrorContext::class, $exception);
229230
$this->assertSame(E_NOTICE, $exception->getSeverity());
231+
$this->assertSame(__FILE__, $exception->getFile());
232+
$this->assertSame($line, $exception->getLine());
233+
$this->assertNotEmpty($exception->getTrace());
234+
$this->assertSame(1, $exception->count);
230235
};
231236

232237
$logger
@@ -239,6 +244,7 @@ public function testHandleError()
239244
$handler->setDefaultLogger($logger, E_NOTICE);
240245
$handler->screamAt(E_NOTICE);
241246
unset($undefVar);
247+
$line = __LINE__ + 1;
242248
@$undefVar++;
243249

244250
restore_error_handler();

src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,8 @@ public function collect(Request $request, Response $response, \Exception $except
4949
public function lateCollect()
5050
{
5151
if (null !== $this->logger) {
52-
$this->data = $this->computeErrorsCount();
53-
5452
$containerDeprecationLogs = $this->getContainerDeprecationLogs();
55-
$this->data['deprecation_count'] += count($containerDeprecationLogs);
53+
$this->data = $this->computeErrorsCount($containerDeprecationLogs);
5654
$this->data['compiler_logs'] = $this->getContainerCompilerLogs();
5755
$this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs));
5856
$this->data = $this->cloneVar($this->data);
@@ -113,11 +111,10 @@ private function getContainerDeprecationLogs()
113111
return array();
114112
}
115113

116-
$stubs = array();
117114
$bootTime = filemtime($file);
118115
$logs = array();
119116
foreach (unserialize(file_get_contents($file)) as $log) {
120-
$log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line']));
117+
$log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count']));
121118
$log['timestamp'] = $bootTime;
122119
$log['priority'] = 100;
123120
$log['priorityName'] = 'DEBUG';
@@ -159,15 +156,34 @@ private function sanitizeLogs($logs)
159156
continue;
160157
}
161158

159+
$message = $log['message'];
162160
$exception = $log['context']['exception'];
163-
$errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$log['message']}", true);
161+
162+
if ($exception instanceof SilencedErrorContext) {
163+
if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
164+
continue;
165+
}
166+
$silencedLogs[$h] = true;
167+
168+
if (!isset($sanitizedLogs[$message])) {
169+
$sanitizedLogs[$message] = $log + array(
170+
'errorCount' => 0,
171+
'scream' => true,
172+
);
173+
}
174+
$sanitizedLogs[$message]['errorCount'] += $exception->count;
175+
176+
continue;
177+
}
178+
179+
$errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true);
164180

165181
if (isset($sanitizedLogs[$errorId])) {
166182
++$sanitizedLogs[$errorId]['errorCount'];
167183
} else {
168184
$log += array(
169185
'errorCount' => 1,
170-
'scream' => $exception instanceof SilencedErrorContext,
186+
'scream' => false,
171187
);
172188

173189
$sanitizedLogs[$errorId] = $log;
@@ -196,8 +212,9 @@ private function isSilencedOrDeprecationErrorLog(array $log)
196212
return false;
197213
}
198214

199-
private function computeErrorsCount()
215+
private function computeErrorsCount(array $containerDeprecationLogs)
200216
{
217+
$silencedLogs = array();
201218
$count = array(
202219
'error_count' => $this->logger->countErrors(),
203220
'deprecation_count' => 0,
@@ -220,14 +237,23 @@ private function computeErrorsCount()
220237
}
221238

222239
if ($this->isSilencedOrDeprecationErrorLog($log)) {
223-
if ($log['context']['exception'] instanceof SilencedErrorContext) {
224-
++$count['scream_count'];
240+
$exception = $log['context']['exception'];
241+
if ($exception instanceof SilencedErrorContext) {
242+
if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
243+
continue;
244+
}
245+
$silencedLogs[$h] = true;
246+
$count['scream_count'] += $exception->count;
225247
} else {
226248
++$count['deprecation_count'];
227249
}
228250
}
229251
}
230252

253+
foreach ($containerDeprecationLogs as $deprecationLog) {
254+
$count['deprecation_count'] += $deprecationLog['count'];
255+
}
256+
231257
ksort($count['priorities']);
232258

233259
return $count;

src/Symfony/Component/HttpKernel/Kernel.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,11 +488,28 @@ protected function initializeContainer()
488488
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
489489
}
490490

491-
$collectedLogs[] = array(
491+
if (isset($collectedLogs[$message])) {
492+
++$collectedLogs[$message]['count'];
493+
494+
return;
495+
}
496+
497+
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
498+
// Clean the trace by removing first frames added by the error handler itself.
499+
for ($i = 0; isset($backtrace[$i]); ++$i) {
500+
if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) {
501+
$backtrace = array_slice($backtrace, 1 + $i);
502+
break;
503+
}
504+
}
505+
506+
$collectedLogs[$message] = array(
492507
'type' => $type,
493508
'message' => $message,
494509
'file' => $file,
495510
'line' => $line,
511+
'trace' => $backtrace,
512+
'count' => 1,
496513
);
497514
});
498515
}
@@ -505,7 +522,7 @@ protected function initializeContainer()
505522
if ($this->debug) {
506523
restore_error_handler();
507524

508-
file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize($collectedLogs));
525+
file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
509526
file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
510527
}
511528
}

src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,35 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property
5353
*/
5454
private $phpDocTypeHelper;
5555

56-
public function __construct(DocBlockFactoryInterface $docBlockFactory = null)
56+
/**
57+
* @var string[]
58+
*/
59+
private $mutatorPrefixes;
60+
61+
/**
62+
* @var string[]
63+
*/
64+
private $accessorPrefixes;
65+
66+
/**
67+
* @var string[]
68+
*/
69+
private $arrayMutatorPrefixes;
70+
71+
/**
72+
* @param DocBlockFactoryInterface $docBlockFactory
73+
* @param string[]|null $mutatorPrefixes
74+
* @param string[]|null $accessorPrefixes
75+
* @param string[]|null $arrayMutatorPrefixes
76+
*/
77+
public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null)
5778
{
5879
$this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
5980
$this->contextFactory = new ContextFactory();
6081
$this->phpDocTypeHelper = new PhpDocTypeHelper();
82+
$this->mutatorPrefixes = null !== $mutatorPrefixes ? $mutatorPrefixes : ReflectionExtractor::$defaultMutatorPrefixes;
83+
$this->accessorPrefixes = null !== $accessorPrefixes ? $accessorPrefixes : ReflectionExtractor::$defaultAccessorPrefixes;
84+
$this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : ReflectionExtractor::$defaultArrayMutatorPrefixes;
6185
}
6286

6387
/**
@@ -137,7 +161,7 @@ public function getTypes($class, $property, array $context = array())
137161
return;
138162
}
139163

140-
if (!in_array($prefix, ReflectionExtractor::$arrayMutatorPrefixes)) {
164+
if (!in_array($prefix, $this->arrayMutatorPrefixes)) {
141165
return $types;
142166
}
143167

@@ -217,7 +241,7 @@ private function getDocBlockFromProperty($class, $property)
217241
*/
218242
private function getDocBlockFromMethod($class, $ucFirstProperty, $type)
219243
{
220-
$prefixes = $type === self::ACCESSOR ? ReflectionExtractor::$accessorPrefixes : ReflectionExtractor::$mutatorPrefixes;
244+
$prefixes = $type === self::ACCESSOR ? $this->accessorPrefixes : $this->mutatorPrefixes;
221245
$prefix = null;
222246

223247
foreach ($prefixes as $prefix) {

0 commit comments

Comments
 (0)