@@ -300,6 +300,9 @@ public static function get_file_component( $file ) {
300300 * line?: string|false,
301301 * error?: WP_Error,
302302 * component?: QM_Component,
303+ * callback_type: string,
304+ * start_line?: int,
305+ * display_file?: string,
303306 * }
304307 */
305308 public static function populate_callback ( array $ callback ) {
@@ -321,9 +324,11 @@ public static function populate_callback( array $callback ) {
321324 if ( is_object ( $ callback ['function ' ][0 ] ) ) {
322325 $ class = get_class ( $ callback ['function ' ][0 ] );
323326 $ access = '-> ' ;
327+ $ callback ['callback_type ' ] = 'method ' ;
324328 } else {
325329 $ class = $ callback ['function ' ][0 ];
326330 $ access = ':: ' ;
331+ $ callback ['callback_type ' ] = 'static_method ' ;
327332 }
328333
329334 $ callback ['name ' ] = self ::shorten_fqn ( $ class . $ access . $ callback ['function ' ][1 ] ) . '() ' ;
@@ -338,46 +343,35 @@ public static function populate_callback( array $callback ) {
338343 if ( 0 === strpos ( $ file , '/ ' ) ) {
339344 $ file = basename ( $ filename );
340345 }
341- $ callback ['name ' ] = sprintf (
342- /* translators: A closure is an anonymous PHP function. 1: Line number, 2: File name */
343- __ ( 'Closure on line %1$d of %2$s ' , 'query-monitor ' ),
344- $ ref ->getStartLine (),
345- $ file
346- );
346+ $ callback ['callback_type ' ] = 'closure ' ;
347+ $ callback ['start_line ' ] = $ ref ->getStartLine ();
348+ $ callback ['display_file ' ] = $ file ;
347349 } else {
348- /* translators: A closure is an anonymous PHP function */
349- $ callback ['name ' ] = __ ( 'Unknown closure ' , 'query-monitor ' );
350+ $ callback ['callback_type ' ] = 'unknown_closure ' ;
350351 }
351352 } else {
352353 // the object should have a __invoke() method
353354 $ class = get_class ( $ callback ['function ' ] );
354355 $ callback ['name ' ] = self ::shorten_fqn ( $ class ) . '->__invoke() ' ;
356+ $ callback ['callback_type ' ] = 'invokable ' ;
355357 $ ref = new ReflectionMethod ( $ class , '__invoke ' );
356358 }
357359 } else {
358360 $ callback ['name ' ] = self ::shorten_fqn ( $ callback ['function ' ] ) . '() ' ;
361+ $ callback ['callback_type ' ] = 'function ' ;
359362 $ ref = new ReflectionFunction ( $ callback ['function ' ] );
360363 }
361364
362365 $ callback ['file ' ] = $ ref ->getFileName ();
363366 $ callback ['line ' ] = $ ref ->getStartLine ();
364367
365- // https://github.com/facebook/hhvm/issues/5856
368+ // Handle legacy create_function() lambdas (PHP 7.4 only, removed in PHP 8.0)
366369 $ name = trim ( $ ref ->getName () );
367-
368- if ( '__lambda_func ' === $ name || 0 === strpos ( $ name , 'lambda_ ' ) ) {
369- if ( $ callback ['file ' ] && preg_match ( '|(?P<file>.*)\((?P<line>[0-9]+)\)| ' , $ callback ['file ' ], $ matches ) ) {
370- $ callback ['file ' ] = $ matches ['file ' ];
371- $ callback ['line ' ] = $ matches ['line ' ];
372- $ file = trim ( self ::standard_dir ( $ callback ['file ' ], '' ), '/ ' );
373- /* translators: 1: Line number, 2: File name */
374- $ callback ['name ' ] = sprintf ( __ ( 'Anonymous function on line %1$d of %2$s ' , 'query-monitor ' ), $ callback ['line ' ], $ file );
375- } else {
376- // https://github.com/facebook/hhvm/issues/5807
377- unset( $ callback ['line ' ], $ callback ['file ' ] );
378- $ callback ['name ' ] = $ name . '() ' ;
379- $ callback ['error ' ] = new WP_Error ( 'unknown_lambda ' , __ ( 'Unable to determine source of lambda function ' , 'query-monitor ' ) );
380- }
370+ if ( 0 === strpos ( $ name , 'lambda_ ' ) ) {
371+ // Just use the lambda name as-is, these are from deprecated create_function()
372+ $ callback ['name ' ] = $ name . '() ' ;
373+ $ callback ['callback_type ' ] = 'lambda ' ;
374+ unset( $ callback ['file ' ], $ callback ['line ' ] );
381375 }
382376
383377 if ( ! empty ( $ callback ['file ' ] ) ) {
@@ -388,6 +382,7 @@ public static function populate_callback( array $callback ) {
388382 } catch ( ReflectionException $ e ) {
389383
390384 $ callback ['error ' ] = new WP_Error ( 'reflection_exception ' , $ e ->getMessage () );
385+ $ callback ['callback_type ' ] = 'unknown ' ;
391386
392387 }
393388
@@ -397,6 +392,45 @@ public static function populate_callback( array $callback ) {
397392
398393 }
399394
395+ /**
396+ * Generate the translated callback name from callback properties.
397+ *
398+ * @param array<string, mixed> $callback Callback data array.
399+ * @return string Translated callback name.
400+ */
401+ public static function get_callback_name ( array $ callback ) {
402+ if ( isset ( $ callback ['name ' ] ) ) {
403+ return $ callback ['name ' ];
404+ }
405+
406+ if ( ! isset ( $ callback ['callback_type ' ] ) ) {
407+ return '' ;
408+ }
409+
410+ switch ( $ callback ['callback_type ' ] ) {
411+ case 'closure ' :
412+ return sprintf (
413+ /* translators: A closure is an anonymous PHP function. 1: Line number, 2: File name */
414+ __ ( 'Closure on line %1$d of %2$s ' , 'query-monitor ' ),
415+ $ callback ['start_line ' ],
416+ $ callback ['display_file ' ]
417+ );
418+
419+ case 'unknown_closure ' :
420+ /* translators: A closure is an anonymous PHP function */
421+ return __ ( 'Unknown closure ' , 'query-monitor ' );
422+
423+ case 'function ' :
424+ case 'method ' :
425+ case 'static_method ' :
426+ case 'invokable ' :
427+ case 'lambda ' :
428+ case 'unknown ' :
429+ default :
430+ return $ callback ['name ' ] ?? '' ;
431+ }
432+ }
433+
400434 /**
401435 * @return bool
402436 */
0 commit comments