@@ -20,6 +20,7 @@ class DeprecationErrorHandler
20
20
{
21
21
const MODE_WEAK = 'weak ' ;
22
22
const MODE_WEAK_VENDORS = 'weak_vendors ' ;
23
+ const MODE_WEAK_LAGGING_VENDORS = 'weak_lagging_vendors ' ;
23
24
const MODE_DISABLED = 'disabled ' ;
24
25
25
26
private static $ isRegistered = false ;
@@ -30,6 +31,8 @@ class DeprecationErrorHandler
30
31
* The following reporting modes are supported:
31
32
* - use "weak" to hide the deprecation report but keep a global count;
32
33
* - use "weak_vendors" to act as "weak" but only for vendors;
34
+ * - use "weak_lagging_vendors" to act as "weak" but only for vendors that
35
+ * failed to keep up with their upstream dependencies deprecations;
33
36
* - use "/some-regexp/" to stop the test suite whenever a deprecation
34
37
* message matches the given regular expression;
35
38
* - use a number to define the upper bound of allowed deprecations,
@@ -54,24 +57,29 @@ public static function register($mode = 0)
54
57
if (false === $ mode ) {
55
58
$ mode = getenv ('SYMFONY_DEPRECATIONS_HELPER ' );
56
59
}
57
- if (DeprecationErrorHandler::MODE_WEAK !== $ mode && DeprecationErrorHandler::MODE_WEAK_VENDORS !== $ mode && (!isset ($ mode [0 ]) || '/ ' !== $ mode [0 ])) {
60
+ if (!in_array ($ mode , array (
61
+ DeprecationErrorHandler::MODE_WEAK ,
62
+ DeprecationErrorHandler::MODE_WEAK_VENDORS ,
63
+ DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS ,
64
+ ), true ) && (!isset ($ mode [0 ]) || '/ ' !== $ mode [0 ])) {
58
65
$ mode = preg_match ('/^[1-9][0-9]*$/ ' , $ mode ) ? (int ) $ mode : 0 ;
59
66
}
60
67
61
68
return $ memoizedMode = $ mode ;
62
69
};
63
70
64
-
65
71
$ deprecations = array (
66
72
'unsilencedCount ' => 0 ,
67
73
'remainingCount ' => 0 ,
68
74
'legacyCount ' => 0 ,
69
75
'otherCount ' => 0 ,
76
+ 'lagging vendorCount ' => 0 ,
70
77
'remaining vendorCount ' => 0 ,
71
78
'unsilenced ' => array (),
72
79
'remaining ' => array (),
73
80
'legacy ' => array (),
74
81
'other ' => array (),
82
+ 'lagging vendor ' => array (),
75
83
'remaining vendor ' => array (),
76
84
);
77
85
$ deprecationHandler = function ($ type , $ msg , $ file , $ line , $ context = array ()) use (&$ deprecations , $ getMode , $ UtilPrefix ) {
@@ -85,8 +93,9 @@ public static function register($mode = 0)
85
93
$ trace = debug_backtrace (true );
86
94
$ group = 'other ' ;
87
95
$ isVendor = false ;
88
- $ isWeak = DeprecationErrorHandler::MODE_WEAK === $ mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode && $ isVendor = self ::inVendors ($ file ));
89
-
96
+ $ isWeak = DeprecationErrorHandler::MODE_WEAK === $ mode ||
97
+ (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode && $ isVendor = self ::inVendors ($ file )) ||
98
+ (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $ mode && $ isLaggingVendor = self ::isLaggingVendor ($ trace ));
90
99
$ i = count ($ trace );
91
100
while (1 < $ i && (!isset ($ trace [--$ i ]['class ' ]) || ('ReflectionMethod ' === $ trace [$ i ]['class ' ] || 0 === strpos ($ trace [$ i ]['class ' ], 'PHPUnit_ ' ) || 0 === strpos ($ trace [$ i ]['class ' ], 'PHPUnit \\' )))) {
6D4E
92
101
// No-op
@@ -119,6 +128,8 @@ public static function register($mode = 0)
119
128
|| in_array ('legacy ' , $ Test ::getGroups ($ class , $ method ), true )
120
129
) {
121
130
$ group = 'legacy ' ;
131
+ } elseif (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $ mode && $ isLaggingVendor ) {
132
+ $ group = 'lagging vendor ' ;
122
133
} elseif (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode && $ isVendor ) {
123
134
$ group = 'remaining vendor ' ;
124
135
} else {
@@ -193,13 +204,16 @@ public static function register($mode = 0)
193
204
if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode ) {
194
205
$ groups [] = 'remaining vendor ' ;
195
206
}
207
+ if (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $ mode ) {
208
+ $ groups [] = 'lagging vendor ' ;
209
+ }
196
210
array_push ($ groups , 'legacy ' , 'other ' );
197
211
198
212
foreach ($ groups as $ group ) {
199
213
if ($ deprecations [$ group .'Count ' ]) {
200
214
echo "\n" , $ colorize (
201
215
sprintf ('%s deprecation notices (%d) ' , ucfirst ($ group ), $ deprecations [$ group .'Count ' ]),
202
- ' legacy ' !== $ group && 'remaining vendor ' !== $ group
216
+ ! in_array ( $ group, array ( ' legacy ' , 'remaining vendor ' , ' lagging vendor ' ), true )
203
217
), "\n" ;
204
218
205
219
uasort ($ deprecations [$ group ], $ cmp );
@@ -228,11 +242,58 @@ public static function register($mode = 0)
228
242
}
229
243
}
230
244
231
- private static function inVendors (string $ path ): bool
245
+ private static function isLaggingVendor (array $ trace ): bool
246
+ {
247
+ $ erroringFile = $ erroringPackage = null ;
248
+ foreach ($ trace as $ line ) {
249
+ if (!isset ($ line ['file ' ])) {
250
+ continue ;
251
+ }
252
+ $ file = $ line ['file ' ];
253
+ if ('- ' === $ file ) {
254
+ continue ;
255
+ }
256
+ if (!self ::inVendors ($ file )) {
257
+ return false ;
258
+ }
259
+ if (null !== $ erroringFile && null !== $ erroringPackage ) {
260
+ if (self ::getPackage ($ file ) !== $ erroringPackage ) {
261
+ return true ;
262
+ }
263
+ } else {
264
+ $ erroringFile = $ file ;
265
+ $ erroringPackage = self ::getPackage ($ file );
266
+ }
267
+ }
268
+
269
+ return false ;
270
+ }
271
+
272
+ /**
273
+ * inVendors() should always be called prior to calling this method.
274
+ */
275
+ private static function getPackage (string $ path ): string
276
+ {
277
+ $ path = realpath ($ path ) ?: $ path ;
278
+ foreach (self ::getVendors () as $ vendorRoot ) {
279
+ if (0 === strpos ($ path , $ vendorRoot )) {
280
+ $ relativePath = substr ($ path , strlen ($ vendorRoot ) + 1 );
281
+ $ vendor = strstr ($ relativePath , DIRECTORY_SEPARATOR , true );
282
+
283
+ return $ vendor .'/ ' .strstr (substr ($ relativePath , strlen ($ vendor ) + 1 ), DIRECTORY_SEPARATOR , true );
284
+ }
285
+ }
286
+
287
+ throw new \RuntimeException ('No vendors found ' );
288
+ }
289
+
290
+ private static function getVendors (): array
232
291
{
233
292
/** @var string[] absolute paths to vendor directories */
234
293
static $ vendors ;
294
+
235
295
if (null === $ vendors ) {
296
+ $ vendors = array ();
236
297
foreach (get_declared_classes () as $ class ) {
237
298
if ('C ' === $ class [0 ] && 0 === strpos ($ class , 'ComposerAutoloaderInit ' )) {
238
299
$ r = new \ReflectionClass ($ class );
@@ -243,8 +304,14 @@ private static function inVendors(string $path): bool
243
304
}
244
305
}
245
306
}
307
+
308
+ return $ vendors ;
309
+ }
310
+
311
+ private static function inVendors (string $ path ): bool
312
+ {
246
313
$ path = realpath ($ path ) ?: $ path ;
247
- foreach ($ vendors as $ vendor ) {
314
+ foreach (self :: getVendors () as $ vendor ) {
248
315
if (0 === strpos ($ path , $ vendor ) && false !== strpbrk (substr ($ path , strlen ($ vendor ), 1 ), '/ ' .DIRECTORY_SEPARATOR )) {
249
316
return true ;
250
317
}
0 commit comments