@@ -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
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 \\' )))) {
92
101
// No-op
@@ -114,6 +123,8 @@ public static function register($mode = 0)
114
123
|| in_array ('legacy ' , $ Test ::getGroups ($ class , $ method ), true )
115
124
) {
116
125
$ group = 'legacy ' ;
126
+ } elseif (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $ mode && $ isLaggingVendor ) {
127
+ $ group = 'lagging vendor ' ;
117
128
} elseif (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode && $ isVendor ) {
118
129
$ group = 'remaining vendor ' ;
119
130
} else {
@@ -188,13 +199,16 @@ public static function register($mode = 0)
188
199
if (DeprecationErrorHandler::MODE_WEAK_VENDORS === $ mode ) {
189
200
$ groups [] = 'remaining vendor ' ;
190
201
}
202
+ if (DeprecationErrorHandler::MODE_WEAK_LAGGING_VENDORS === $ mode ) {
203
+ $ groups [] = 'lagging vendor ' ;
204
+ }
191
205
array_push ($ groups , 'legacy ' , 'other ' );
192
206
193
207
foreach ($ groups as $ group ) {
194
208
if ($ deprecations [$ group .'Count ' ]) {
195
209
echo "\n" , $ colorize (
196
210
sprintf ('%s deprecation notices (%d) ' , ucfirst ($ group ), $ deprecations [$ group .'Count ' ]),
197
- ' legacy ' !== $ group && 'remaining vendor ' !== $ group
211
+ ! in_array ( $ group, array ( ' legacy ' , 'remaining vendor ' , ' lagging vendor ' ), true )
198
212
), "\n" ;
199
213
200
214
uasort ($ deprecations [$ group ], $ cmp );
@@ -223,10 +237,52 @@ public static function register($mode = 0)
223
237
}
224
238
}
225
239
226
- private static function inVendors (string $ path ): bool
240
+ private static function isLaggingVendor (array $ trace ): bool
241
+ {
242
+ foreach ($ trace as $ line ) {
243
+ if (isset ($ line ['file ' ])) {
244
+ $ file = $ line ['file ' ];
245
+ if ('- ' === $ file ) {
246
+ continue ;
247
+ }
248
+ if (!self ::inVendors ($ file )) {
249
+ return false ;
250
+ }
251
+ if (isset ($ erroringFile , $ erroringPackage )) {
252
+ if (self ::getPackage ($ file ) !== $ erroringPackage ) {
253
+ return true ;
254
+ }
255
+ } else {
256
+ $ erroringFile = $ file ;
257
+ $ erroringPackage = self ::getPackage ($ file );
258
+ }
259
+ }
260
+ }
261
+
262
+ return false ;
263
+ }
264
+
265
+ /**
266
+ * inVendors() should always be called prior to calling this method.
267
+ */
268
+ private static function getPackage (string $ path ): string
269
+ {
270
+ $ path = realpath ($ path ) ?: $ path ;
271
+ foreach (self ::getVendors () as $ vendorRoot ) {
272
+ if (0 === strpos ($ path , $ vendorRoot )) {
273
+ $ relativePath = substr ($ path , strlen ($ vendorRoot ) + 1 );
274
+ $ vendor = strstr ($ relativePath , DIRECTORY_SEPARATOR , true );
275
+
276
+ return $ vendor .'/ ' .strstr (substr ($ relativePath , strlen ($ vendor ) + 1 ), DIRECTORY_SEPARATOR , true );
277
+ }
278
+ }
279
+ }
280
+
281
+ private static function getVendors (): ?array
227
282
{
228
283
/** @var string[] absolute paths to vendor directories */
229
284
static $ vendors ;
285
+
230
286
if (null === $ vendors ) {
231
287
foreach (get_declared_classes () as $ class ) {
232
288
if ('C ' === $ class [0 ] && 0 === strpos ($ class , 'ComposerAutoloaderInit ' )) {
@@ -238,8 +294,14 @@ private static function inVendors(string $path): bool
238
294
}
239
295
}
240
296
}
297
+
298
+ return $ vendors ;
299
+ }
300
+
301
+ private static function inVendors (string $ path ): bool
302
+ {
241
303
$ path = realpath ($ path ) ?: $ path ;
242
- foreach ($ vendors as $ vendor ) {
304
+ foreach (self :: getVendors () as $ vendor ) {
243
305
if (0 === strpos ($ path , $ vendor ) && false !== strpbrk (substr ($ path , strlen ($ vendor ), 1 ), '/ ' .DIRECTORY_SEPARATOR )) {
244
306
return true ;
245
307
}
0 commit comments