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

Skip to content

Commit 1c73f9c

Browse files
committed
[PhpUnitBridge] Url encoded deprecations helper config
1 parent e0c4528 commit 1c73f9c

18 files changed

+1049
-159
lines changed

src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php

Lines changed: 89 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,40 @@
1111

1212
namespace Symfony\Bridge\PhpUnit;
1313

14+
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Configuration;
15+
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation;
16+
1417
/**
1518
* Catch deprecation notices and print a summary report at the end of the test suite.
1619
*
1720
* @author Nicolas Grekas <[email protected]>
1821
*/
1922
class DeprecationErrorHandler
2023
{
21-
const MODE_WEAK = 'weak';
24+
/**
25+
* @deprecated since Symfony 4.3, use max[self]=0 instead
26+
*/
2227
const MODE_WEAK_VENDORS = 'weak_vendors';
28+
2329
const MODE_DISABLED = 'disabled';
30+
const MODE_WEAK = 'max[total]=999999&verbose=0';
31+
const MODE_STRICT = 'max[total]=0';
2432

25-
private $mode = false;
26-
private $resolvedMode = false;
33+
private $mode;
34+
private $configuration;
2735
private $deprecations = [
2836
'unsilencedCount' => 0,
29-
'remainingCount' => 0,
37+
'remaining selfCount' => 0,
3038
'legacyCount' => 0,
3139
'otherCount' => 0,
32-
'remaining vendorCount' => 0,
40+
'remaining directCount' => 0,
41+
'remaining indirectCount' => 0,
3342
'unsilenced' => [],
34-
'remaining' => [],
43+
'remaining self' => [],
3544
'legacy' => [],
3645
'other' => [],
37-
'remaining vendor' => [],
46+
'remaining direct' => [],
47+
'remaining indirect' => [],
3848
];
3949

4050
private static $isRegistered = false;
@@ -43,13 +53,16 @@ class DeprecationErrorHandler
4353
/**
4454
* Registers and configures the deprecation handler.
4555
*
46-
* The following reporting modes are supported:
47-
* - use "weak" to hide the deprecation report but keep a global count;
48-
* - use "weak_vendors" to fail only on deprecations triggered in your own code;
49-
* - use "/some-regexp/" to stop the test suite whenever a deprecation
50-
* message matches the given regular expression;
51-
* - use a number to define the upper bound of allowed deprecations,
52-
* making the test suite fail whenever more notices are triggered.
56+
* The mode is a query string with options:
57+
* - "disabled" to disable the deprecation handler
58+
* - "verbose" to enable/disable displaying the deprecation report
59+
* - "max" to configure the number of deprecations to allow before exiting with a non-zero
60+
* status code; it's an array with keys "total", "self", "direct" and "indirect"
61+
*
62+
* The default mode is "max[total]=0&verbose=1".
63+
*
64+
* The mode can alternatively be "/some-regexp/" to stop the test suite whenever
65+
* a deprecation message matches the given regular expression.
5366
*
5467
* @param int|string|false $mode The reporting mode, defaults to not allowing any deprecations
5568
*/
@@ -108,76 +121,41 @@ public static function collectDeprecations($outputFile)
108121
*/
109122
public function handleError($type, $msg, $file, $line, $context = [])
110123
{
111-
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || self::MODE_DISABLED === $mode = $this->getMode()) {
124+
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || !$this->getConfiguration()->isEnabled()) {
112125
$ErrorHandler = self::$utilPrefix.'ErrorHandler';
113126

114127
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
115128
}
116129

117-
$trace = debug_backtrace();
130+
$deprecation = new Deprecation($msg, debug_backtrace(), $file);
118131
$group = 'other';
119-
$isVendor = self::MODE_WEAK_VENDORS === $mode && self::inVendors($file);
120132

121-
$i = \count($trace);
122-
while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
123-
// No-op
124-
}
125-
126-
if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
127-
if (isset($trace[$i]['class']) && 0 === strpos($trace[$i]['class'], 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor')) {
128-
$parsedMsg = unserialize($msg);
129-
$msg = $parsedMsg['deprecation'];
130-
$class = $parsedMsg['class'];
131-
$method = $parsedMsg['method'];
132-
// If the deprecation has been triggered via
133-
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
134-
// then we need to use the serialized information to determine
135-
// if the error has been triggered from vendor code.
136-
$isVendor = self::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && self::inVendors($parsedMsg['triggering_file']);
137-
} else {
138-
$class = isset($trace[$i]['object']) ? \get_class($trace[$i]['object']) : $trace[$i]['class'];
139-
$method = $trace[$i]['function'];
140-
}
141-
142-
$Test = self::$utilPrefix.'Test';
133+
if ($deprecation->originatesFromAnObject()) {
134+
$class = $deprecation->originatingClass();
135+
$method = $deprecation->originatingMethod();
143136

144137
if (0 !== error_reporting()) {
145138
$group = 'unsilenced';
146-
} elseif (0 === strpos($method, 'testLegacy')
147-
|| 0 === strpos($method, 'provideLegacy')
148-
|| 0 === strpos($method, 'getLegacy')
149-
|| strpos($class, '\Legacy')
150-
|| \in_array('legacy', $Test::getGroups($class, $method), true)
151-
) {
139+
} elseif ($deprecation->isLegacy(self::$utilPrefix)) {
152140
$group = 'legacy';
153-
} elseif ($isVendor) {
154-
$group = 'remaining vendor';
141+
} elseif (!$deprecation->isSelf()) {
142+
$group = $deprecation->isIndirect() ? 'remaining indirect' : 'remaining direct';
155143
} else {
156-
$group = 'remaining';
144+
$group = 'remaining self';
157145
}
158146

159-
if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
160-
$e = new \Exception($msg);
161-
$r = new \ReflectionProperty($e, 'trace');
162-
$r->setAccessible(true);
163-
$r->setValue($e, \array_slice($trace, 1, $i));
164-
165-
echo "\n".ucfirst($group).' deprecation triggered by '.$class.'::'.$method.':';
166-
echo "\n".$msg;
167-
echo "\nStack trace:";
168-
echo "\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $e->getTraceAsString());
169-
echo "\n";
147+
if ($this->getConfiguration()->shouldDisplayStackTrace($msg)) {
148+
echo "\n".ucfirst($group).' '.$deprecation->toString();
170149

171150
exit(1);
172151
}
173-
174-
if ('legacy' !== $group && self::MODE_WEAK !== $mode) {
152+
if ('legacy' !== $group) {
175153
$ref = &$this->deprecations[$group][$msg]['count'];
176154
++$ref;
177155
$ref = &$this->deprecations[$group][$msg][$class.'::'.$method];
178156
++$ref;
179157
}
180-
} elseif (self::MODE_WEAK !== $mode) {
158+
} else {
181159
$ref = &$this->deprecations[$group][$msg]['count'];
182160
++$ref;
183161
}
@@ -190,124 +168,88 @@ public function handleError($type, $msg, $file, $line, $context = [])
190168
*/
191169
public function shutdown()
192170
{
193-
$mode = $this->getMode();
171+
$configuration = $this->getConfiguration();
194172

195-
if (isset($mode[0]) && '/' === $mode[0]) {
173+
if ($configuration->isInRegexMode()) {
196174
return;
197175
}
198176

199177
$currErrorHandler = set_error_handler('var_dump');
200178
restore_error_handler();
201179

202180
if ($currErrorHandler !== [$this, 'handleError']) {
203-
echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true, $mode), "\n";
204-
}
205-
206-
$groups = ['unsilenced', 'remaining'];
207-
208-
if (self::MODE_WEAK_VENDORS === $mode) {
209-
$groups[] = 'remaining vendor';
181+
echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n";
210182
}
211183

212-
array_push($groups, 'legacy', 'other');
184+
$groups = ['unsilenced', 'remaining self', 'remaining direct', 'remaining indirect', 'legacy', 'other'];
213185

214-
$this->displayDeprecations($groups, $mode);
186+
$this->displayDeprecations($groups, $configuration);
215187

216188
// store failing status
217-
$isFailing = self::MODE_WEAK !== $mode && $mode < $this->deprecations['unsilencedCount'] + $this->deprecations['remainingCount'] + $this->deprecations['otherCount'];
189+
$isFailing = !$configuration->tolerates($this->deprecations);
218190

219191
// reset deprecations array
220192
foreach ($this->deprecations as $group => $arrayOrInt) {
221193
$this->deprecations[$group] = \is_int($arrayOrInt) ? 0 : [];
222194
}
223195

224-
register_shutdown_function(function () use ($isFailing, $groups, $mode) {
196+
register_shutdown_function(function () use ($isFailing, $groups, $configuration) {
225197
foreach ($this->deprecations as $group => $arrayOrInt) {
226198
if (0 < (\is_int($arrayOrInt) ? $arrayOrInt : \count($arrayOrInt))) {
227199
echo "Shutdown-time deprecations:\n";
228200
break;
229201
}
230202
}
231203

232-
$this->displayDeprecations($groups, $mode);
204+
$this->displayDeprecations($groups, $configuration);
233205

234-
if ($isFailing || self::MODE_WEAK !== $mode && $mode < $this->deprecations['unsilencedCount'] + $this->deprecations['remainingCount'] + $this->deprecations['otherCount']) {
206+
if ($isFailing || !$configuration->tolerates($this->deprecations)) {
235207
exit(1);
236208
}
237209
});
238210
}
239211

240-
private function getMode()
212+
private function getConfiguration()
241213
{
242-
if (false !== $this->resolvedMode) {
243-
return $this->resolvedMode;
214+
if (null !== $this->configuration) {
215+
return $this->configuration;
244216
}
245-
246217
if (false === $mode = $this->mode) {
247218
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
248219
}
249-
250-
if (self::MODE_DISABLED !== $mode
251-
&& self::MODE_WEAK !== $mode
252-
&& self::MODE_WEAK_VENDORS !== $mode
253-
&& (!isset($mode[0]) || '/' !== $mode[0])
254-
) {
255-
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
220+
if ('strict' === $mode) {
221+
return $this->configuration = Configuration::inStrictMode();
256222
}
257-
258-
return $this->resolvedMode = $mode;
259-
}
260-
261-
/**
262-
* @param string $path
263-
*
264-
* @return bool
265-
*/
266-
private static function inVendors($path)
267-
{
268-
/** @var string[] absolute paths to vendor directories */
269-
static $vendors;
270-
271-
if (null === $vendors) {
272-
foreach (get_declared_classes() as $class) {
273-
if ('C' !== $class[0] || 0 !== strpos($class, 'ComposerAutoloaderInit')) {
274-
continue;
275-
}
276-
277-
$r = new \ReflectionClass($class);
278-
$v = \dirname(\dirname($r->getFileName()));
279-
280-
if (file_exists($v.'/composer/installed.json')) {
281-
$vendors[] = $v;
282-
}
283-
}
223+
if (self::MODE_DISABLED === $mode) {
224+
return $this->configuration = Configuration::inDisabledMode();
284225
}
285-
286-
$realPath = realpath($path);
287-
288-
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
289-
return true;
226+
if ('weak' === $mode) {
227+
return $this->configuration = Configuration::inWeakMode();
228+
}
229+
if (self::MODE_WEAK_VENDORS === $mode) {
230+
echo sprintf('Setting SYMFONY_DEPRECATIONS_HELPER to "%s" is deprecated in favor of "max[self]=0"', $mode).PHP_EOL;
231+
exit(1);
232+
}
233+
if (isset($mode[0]) && '/' === $mode[0]) {
234+
return $this->configuration = Configuration::fromRegex($mode);
290235
}
291236

292-
foreach ($vendors as $vendor) {
293-
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
294-
return true;
295-
}
237+
if (preg_match('/^[1-9][0-9]*$/', (string) $mode)) {
238+
return $this->configuration = Configuration::fromNumber($mode);
296239
}
297240

298-
return false;
241+
return $this->configuration = Configuration::fromUrlEncodedString((string) $mode);
299242
}
300243

301244
/**
302245
* @param string $str
303246
* @param bool $red
304-
* @param mixed $mode
305247
*
306248
* @return string
307249
*/
308-
private static function colorize($str, $red, $mode)
250+
private static function colorize($str, $red)
309251
{
310-
if (!self::hasColorSupport() || self::MODE_WEAK === $mode) {
252+
if (!self::hasColorSupport()) {
311253
return $str;
312254
}
313255

@@ -317,36 +259,36 @@ private static function colorize($str, $red, $mode)
317259
}
318260

319261
/**
320-
* @param string[] $groups
321-
* @param mixed $mode
262+
* @param string[] $groups
263+
* @param Configuration $configuration
322264
*/
323-
private function displayDeprecations($groups, $mode)
265+
private function displayDeprecations($groups, $configuration)
324266
{
325267
$cmp = function ($a, $b) {
326268
return $b['count'] - $a['count'];
327269
};
328270

329271
foreach ($groups as $group) {
330-
if (!$this->deprecations[$group.'Count']) {
331-
continue;
332-
}
272+
if ($this->deprecations[$group.'Count']) {
273+
echo "\n", self::colorize(
274+
sprintf('%s deprecation notices (%d)', ucfirst($group), $this->deprecations[$group.'Count']),
275+
'legacy' !== $group && 'remaining indirect' !== $group
276+
), "\n";
333277

334-
echo "\n", self::colorize(
335-
sprintf('%s deprecation notices (%d)', ucfirst($group), $this->deprecations[$group.'Count']),
336-
'legacy' !== $group && 'remaining vendor' !== $group,
337-
$mode
338-
), "\n";
339-
340-
uasort($this->deprecations[$group], $cmp);
278+
if (!$configuration->verboseOutput()) {
279+
continue;
280+
}
281+
uasort($this->deprecations[$group], $cmp);
341282

342-
foreach ($this->deprecations[$group] as $msg => $notices) {
343-
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
283+
foreach ($this->deprecations[$group] as $msg => $notices) {
284+
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
344285

345-
arsort($notices);
286+
arsort($notices);
346287

347-
foreach ($notices as $method => $count) {
348-
if ('count' !== $method) {
349-
echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
288+
foreach ($notices as $method => $count) {
289+
if ('count' !== $method) {
290+
echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
291+
}
350292
}
351293
}
352294
}

0 commit comments

Comments
 (0)