8000 Merge branch '2.8' into 3.0 · symfony/symfony@06dd574 · GitHub
[go: up one dir, main page]

Skip to content

Commit 06dd574

Browse files
committed
Merge branch '2.8' into 3.0
2 parents be381af + 3a57b77 commit 06dd574

File tree

18 files changed

+169
-54
lines changed

18 files changed

+169
-54
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,29 @@
1919
class DeprecationErrorHandler
2020
{
2121
const MODE_WEAK = 'weak';
22-
const MODE_WEAK_VERBOSE = 'weak-verbose';
2322

2423
private static $isRegistered = false;
2524

26-
public static function register($mode = false)
25+
/**
26+
* Registers and configures the deprecation handler.
27+
*
28+
* The following reporting modes are supported:
29+
* - use "weak" to hide the deprecation report but keep a global count;
30+
* - use "/some-regexp/" to stop the test suite whenever a deprecation
31+
* message matches the given regular expression;
32+
* - use a number to define the upper bound of allowed deprecations,
33+
* making the test suite fail whenever more notices are trigerred.
34+
*
35+
* @param int|string|false $mode The reporting mode. Defaults to not allowing any deprecations.
36+
*/
37+
public static function register($mode = 0)
2738
{
2839
if (self::$isRegistered) {
2940
return;
3041
}
42+
if (self::MODE_WEAK !== $mode && (!isset($mode[0]) || '/' !== $mode[0])) {
43+
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
44+
}
3145
$deprecations = array(
3246
'unsilencedCount' => 0,
3347
'remainingCount' => 0,
@@ -147,7 +161,8 @@ public static function register($mode = false)
147161
if (!empty($notices)) {
148162
echo "\n";
149163
}
150-
if (self::MODE_WEAK !== $mode && self::MODE_WEAK_VERBOSE !== $mode && ($deprecations['unsilenced'] || $deprecations['remaining'] || $deprecations['other'])) {
164+
165+
if (DeprecationErrorHandler::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) {
151166
exit(1);
152167
}
153168
});

src/Symfony/Bridge/PhpUnit/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ It comes with the following features:
1212
* display the stack trace of a deprecation on-demand.
1313

1414
By default any non-legacy-tagged or any non-@-silenced deprecation notices will
15-
make tests fail.
16-
This can be changed by setting the `SYMFONY_DEPRECATIONS_HELPER` environment
17-
variable to `weak` or `weak-verbose`. This will make the bridge ignore
18-
deprecation notices and is useful to projects that must use deprecated interfaces
19-
for backward compatibility reasons.
15+
make tests fail. This can be changed by setting the `SYMFONY_DEPRECATIONS_HELPER`
16+
environment variable to the maximum number of deprecations that are allowed to be
17+
triggered before making the test suite fail. Alternatively, setting it to `weak`
18+
will make the bridge ignore any deprecation notices and is useful to projects
19+
that must use deprecated interfaces for backward compatibility reasons.
2020

2121
A summary of deprecation notices is displayed at the end of the test suite:
2222

src/Symfony/Bundle/FrameworkBundle/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ protected function getScript($request)
185185
$code = <<<EOF
186186
<?php
187187
188-
error_reporting($errorReporting & ~E_USER_DEPRECATED);
188+
error_reporting($errorReporting);
189189
190190
if ('$autoloader') {
191191
require_once '$autoloader';

src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
118118
$helper = new DescriptorHelper();
119119
$options['format'] = $input->getOption('format');
120120
$options['raw_text'] = $input->getOption('raw');
121-
$options['output'] = $output;
121+
$options['output'] = $io;
122122
$helper->describe($output, $object, $options);
123123

124124
if (!$input->getArgument('name') && $input->isInteractive()) {

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@
5353
</div>
5454
{% else %}
5555
{# sort collected logs in groups #}
56-
{% set deprecation_logs, debug_logs, info_and_error_logs = [], [], [] %}
56+
{% set deprecation_logs, debug_logs, info_and_error_logs, silenced_logs = [], [], [], [] %}
5757
{% for log in collector.logs %}
5858
{% if log.context.level is defined and log.context.type is defined and log.context.type in [constant('E_DEPRECATED'), constant('E_USER_DEPRECATED')] %}
5959
{% set deprecation_logs = deprecation_logs|merge([log]) %}
60+
{% elseif log.context.scream is defined and log.context.scream == true %}
61+
{% set silenced_logs = silenced_logs|merge([log]) %}
6062
{% elseif log.priorityName == 'DEBUG' %}
6163
{% set debug_logs = debug_logs|merge([log]) %}
6264
{% else %}
@@ -108,6 +110,21 @@
108110
{% endif 57AE %}
109111
</div>
110112
</div>
113+
114+
<div class="tab">
115+
<h3 class="tab-title">Silenced Errors <span class="badge">{{ collector.countscreams|default(0) }}</span></h3>
116+
117+
<div class="tab-content">
118+
{% if silenced_logs is empty %}
119+
<div class="empty">
120+
<p>There are no log messages of this level.</p>
121+
</div>
122+
{% else %}
123+
{{ helper.render_table(silenced_logs) }}
124+
{% endif %}
125+
B41A </div>
126+
</div>
127+
111128
</div>
112129
{% endif %}
113130
{% endblock %}

src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu
3333
{
3434
$validator = $question->getValidator();
3535
$question->setValidator(function ($value) use ($validator) {
36-
if (null !== $validator && is_callable($validator)) {
36+
if (null !== $validator) {
3737
$value = $validator($value);
3838
}
3939

src/Symfony/Component/Console/Helper/Table.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ private function calculateNumberOfColumns()
384384
$columns[] = $this->getNumberOfColumns($row);
385385
}
386386

387-
return $this->numberOfColumns = max($columns);
387+
$this->numberOfColumns = max($columns);
388388
}
389389

390390
private function buildTableRows($rows)
@@ -539,7 +539,7 @@ private function getNumberOfColumns(array $row)
539539
*
540540
* @param array $row
541541
*
542-
* @return array()
542+
* @return array
543543
*/
544544
private function getRowColumns($row)
545545
{
@@ -555,11 +555,9 @@ private function getRowColumns($row)
555555
}
556556

557557
/**
558-
* Gets column width.
559-
*
560-
* @param int $column
558+
* Calculates columns widths.
561559
*
562-
* @return int
560+
* @param array $rows
563561
*/
564562
private function calculateColumnsWidth($rows)
565563
{
@@ -580,8 +578,6 @@ private function calculateColumnsWidth($rows)
580578
/**
581579
* Gets column width.
582580
*
583-
* @param int $column
584-
*
585581
* @return int
586582
*/
587583
private function getColumnSeparatorWidth()

src/Symfony/Component/HttpKernel/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ protected function getScript($request)
105105
$code = <<<EOF
106106
<?php
107107
108-
error_reporting($errorReporting & ~E_USER_DEPRECATED);
108+
error_reporting($errorReporting);
109109
110110
require_once '$requirePath';
111111

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,24 @@
2222
*/
2323
class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
2424
{
25+
private $errorNames = array(
26+
E_DEPRECATED => 'E_DEPRECATED',
27+
E_USER_DEPRECATED => 'E_USER_DEPRECATED',
28+
E_NOTICE => 'E_NOTICE',
29+
E_USER_NOTICE => 'E_USER_NOTICE',
30+
E_STRICT => 'E_STRICT',
31+
E_WARNING => 'E_WARNING',
32+
E_USER_WARNING => 'E_USER_WARNING',
33+
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
34+
E_CORE_WARNING => 'E_CORE_WARNING',
35+
E_USER_ERROR => 'E_USER_ERROR',
36+
E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR',
37+
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
38+
E_PARSE => 'E_PARSE',
39+
E_ERROR => 'E_ERROR',
40+
E_CORE_ERROR => 'E_CORE_ERROR',
41+
);
42+
2543
private $logger;
2644

2745
public function __construct($logger = null)
@@ -106,6 +124,9 @@ private function sanitizeLogs($logs)
106124
if (isset($context['type'], $context['file'], $context['line'], $context['level'])) {
107125
$errorId = md5("{$context['type']}/{$context['line']}/{$context['file']}\x00{$log['message']}", true);
108126
$silenced = !($context['type'] & $context['level']);
127+
if (isset($this->errorNames[$context['type']])) {
128+
$context = array_merge(array('name' => $this->errorNames[$context['type']]), $context);
129+
}
109130

110131
if (isset($errorContextById[$errorId])) {
111132
if (isset($errorContextById[$errorId]['errorCount'])) {

src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ public function getCollectTestData()
7575
),
7676
array(
7777
1,
78-
array(array('message' => 'foo3', 'context' => array('type' => E_USER_WARNING, 'level' => 0, 'file' => __FILE__, 'line' => 123), 'priority' => 100, 'priorityName' => 'DEBUG')),
79-
array(array('message' => 'foo3', 'context' => array('type' => E_USER_WARNING, 'level' => 0, 'file' => __FILE__, 'line' => 123, 'scream' => true), 'priority' => 100, 'priorityName' => 'DEBUG')),
78+
array(array('message' => 'foo3', 'context' => array('name' => 'E_USER_WARNING', 'type' => E_USER_WARNING, 'level' => 0, 'file' => __FILE__, 'line' => 123), 'priority' => 100, 'priorityName' => 'DEBUG')),
79+
array(array('message' => 'foo3', 'context' => array('name' => 'E_USER_WARNING', 'type' => E_USER_WARNING, 'level' => 0, 'file' => __FILE__, 'line' => 123, 'scream' => true), 'priority' => 100, 'priorityName' => 'DEBUG')),
8080
0,
8181
1,
8282
),
@@ -86,7 +86,7 @@ public function getCollectTestData()
8686
array('message' => 'foo3', 'context' => array('type' => E_USER_WARNING, 'level' => 0, 'file' => __FILE__, 'line' => 123), 'priority' => 100, 'priorityName' => 'DEBUG'),
8787
array('message' => 'foo3', 'context' => array('type' => E_USER_WARNING, 'level' => -1, 'file' => __FILE__, 'line' => 123), 'priority' => 100, 'priorityName' => 'DEBUG'),
8888
),
89-
array(array('message' => 'foo3', 'context' => array('type' => E_USER_WARNING, 'level' => -1, 'file' => __FILE__, 'line' => 123, 'errorCount' => 2), 'priority' => 100, 'priorityName' => 'DEBUG')),
89+
array(array('message' => 'foo3', 'context' => array('name' => 'E_USER_WARNING', 'type' => E_USER_WARNING, 'level' => -1, 'file' => __FILE__, 'line' => 123, 'errorCount' => 2), 'priority' => 100, 'priorityName' => 'DEBUG')),
9090
0,
9191
1,
9292
),

src/Symfony/Component/PropertyAccess/PropertyAccessor.php

Lines changed: 64 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,74 @@
2424
*/
2525
class PropertyAccessor implements PropertyAccessorInterface
2626
{
27+
/**
28+
* @internal
29+
*/
2730
const VALUE = 0;
31+
32+
/**
33+
* @internal
34+
*/
2835
const IS_REF = 1;
36+
37+
/**
38+
* @internal
39+
*/
2940
const IS_REF_CHAINED = 2;
41+
42+
/**
43+
* @internal
44+
*/
3045
const ACCESS_HAS_PROPERTY = 0;
46+
47+
/**
48+
* @internal
49+
*/
3150
const ACCESS_TYPE = 1;
51+
52+
/**
53+
* @internal
54+
*/
3255
const ACCESS_NAME = 2;
56+
57+
/**
58+
* @internal
59+
*/
3360
const ACCESS_REF = 3;
61+
62+
/**
63+
* @internal
64+
*/
3465
const ACCESS_ADDER = 4;
66+
67+
/**
68+
* @internal
69+
*/
3570
const ACCESS_REMOVER = 5;
71+
72+
/**
73+
* @internal
74+
*/
3675
const ACCESS_TYPE_METHOD = 0;
76+
77+
/**
78+
* @internal
79+
*/
3780
const ACCESS_TYPE_PROPERTY = 1;
81+
82+
/**
83+
* @internal
84+
*/
3885
const ACCESS_TYPE_MAGIC = 2;
86+
87+
/**
88+
* @internal
89+
*/
3990
const ACCESS_TYPE_ADDER_AND_REMOVER = 3;
91+
92+
/**
93+
* @internal
94+
*/
4095
const ACCESS_TYPE_NOT_FOUND = 4;
4196

4297
/**
@@ -62,6 +117,9 @@ class PropertyAccessor implements PropertyAccessorInterface
62117
/**
63118
* Should not be used by application code. Use
64119
* {@link PropertyAccess::createPropertyAccessor()} instead.
120+
*
121+
* @param bool $magicCall
122+
* @param bool $throwExceptionOnInvalidIndex
65123
*/
66124
public function __construct($magicCall = false, $throwExceptionOnInvalidIndex = false)
67125
{
@@ -365,7 +423,7 @@ private function &readProperty(&$object, $property)
365423
}
366424
} elseif (!$access[self::ACCESS_HAS_PROPERTY] && property_exists($object, $property)) {
367425
// Needed to support \stdClass instances. We need to explicitly
368-
// exclude $classHasProperty, otherwise if in the previous clause
426+
// exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if
369427
// a *protected* property was found on the class, property_exists()
370428
// returns true, consequently the following line will result in a
371429
// fatal error.
@@ -411,7 +469,6 @@ private function getReadAccessInfo($object, $property)
411469
$getsetter = lcfirst($camelProp); // jQuery style, e.g. read: last(), write: last($item)
412470
$isser = 'is'.$camelProp;
413471
$hasser = 'has'.$camelProp;
414-
$classHasProperty = $reflClass->hasProperty($property);
415472

416473
if ($reflClass->hasMethod($getter) && $reflClass->getMethod($getter)->isPublic()) {
417474
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_METHOD;
@@ -429,13 +486,10 @@ private function getReadAccessInfo($object, $property)
429486
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
430487
$access[self::ACCESS_NAME] = $property;
431488
$access[self::ACCESS_REF] = false;
432-
} elseif ($classHasProperty && $reflClass->getProperty($property)->isPublic()) {
489+
} elseif ($access[self::ACCESS_HAS_PROPERTY] && $reflClass->getProperty($property)->isPublic()) {
433490
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
434491
$access[self::ACCESS_NAME] = $property;
435492
$access[self::ACCESS_REF] = true;
436-
437-
$result[self::VALUE] = &$object->$property;
438-
$result[self::IS_REF] = true;
439493
} elseif ($this->magicCall && $reflClass->hasMethod('__call') && $reflClass->getMethod('__call')->isPublic()) {
440494
// we call the getter and hope the __call do the job
441495
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_MAGIC;
@@ -506,7 +560,7 @@ private function writeProperty(&$object, $property, $value)
506560
$this->writeCollection($object, $property, $value, $access[self::ACCESS_ADDER], $access[self::ACCESS_REMOVER]);
507561
} elseif (!$access[self::ACCESS_HAS_PROPERTY] && property_exists($object, $property)) {
508562
// Needed to support \stdClass instances. We need to explicitly
509-
// exclude $classHasProperty, otherwise if in the previous clause
563+
// exclude $access[self::ACCESS_HAS_PROPERTY], otherwise if
510564
// a *protected* property was found on the class, property_exists()
511565
// returns true, consequently the following line will result in a
512566
// fatal error.
@@ -579,7 +633,6 @@ private function writeCollection($object, $property, $collection, $addMethod, $r
579633
private function getWriteAccessInfo($object, $property, $value)
580634
{
581635
$key = get_class($object).'::'.$property;
582-
$guessedAdders = '';
583636

584637
if (isset($this->writePropertyCache[$key])) {
585638
$access = $this->writePropertyCache[$key];
@@ -594,25 +647,17 @@ private function getWriteAccessInfo($object, $property, $value)
594647
if (is_array($value) || $value instanceof \Traversable) {
595648
$methods = $this->findAdderAndRemover($reflClass, $singulars);
596649

597-
if (null === $methods) {
598-
// It is sufficient to include only the adders in the error
599-
// message. If the user implements the adder but not the remover,
600-
// an exception will be thrown in findAdderAndRemover() that
601-
// the remover has to be implemented as well.
602-
$guessedAdders = '"add'.implode('()", "add', $singulars).'()", ';
603-
} else {
650+
if (null !== $methods) {
604651
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_ADDER_AND_REMOVER;
605652
$access[self::ACCESS_ADDER] = $methods[0];
606653
$access[self::ACCESS_REMOVER] = $methods[1];
607654
}
608655
}
609656

610657
if (!isset($access[self::ACCESS_TYPE])) {
611-
$setter = 'set'.$this->camelize($property);
658+
$setter = 'set'.$camelized;
612659
$getsetter = lcfirst($camelized); // jQuery style, e.g. read: last(), write: last($item)
613660

614-
$classHasProperty = $reflClass->hasProperty($property);
615-
616661
if ($this->isMethodAccessible($reflClass, $setter, 1)) {
617662
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_METHOD;
618663
$access[self::ACCESS_NAME] = $setter;
@@ -622,7 +667,7 @@ private function getWriteAccessInfo($object, $property, $value)
622667
} elseif ($this->isMethodAccessible($reflClass, '__set', 2)) {
623668
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
624669
$access[self::ACCESS_NAME] = $property;
625-
} elseif ($classHasProperty && $reflClass->getProperty($property)->isPublic()) {
670+
} elseif ($access[self::ACCESS_HAS_PROPERTY] && $reflClass->getProperty($property)->isPublic()) {
626671
$access[self::ACCESS_TYPE] = self::ACCESS_TYPE_PROPERTY;
627672
$access[self::ACCESS_NAME] = $property;
628673
} elseif ($this->magicCall && $this->isMethodAccessible($reflClass, '__call', 2)) {

0 commit comments

Comments
 (0)
0