Make WordPress Core

Opened 6 years ago

Closed 6 years ago

#45192 closed defect (bug) (fixed)

WP_DEBUG notice when classic editor is forced and static methods used causes fatal errors.

Reported by: claudiulodro's profile claudiulodro Owned by: pento's profile pento
Milestone: 5.0 Priority: normal
Severity: normal Version: 5.0
Component: Editor Keywords: has-patch fixed-5.0
Focuses: administration Cc:

Description

Hi folks,

I've tested this bug with the latest version of the Classic Editor and the WP 5.0 beta released yesterday. The ReflectionFunction class does not seem to properly handle static functions of the form 'ClassName::method_name'. Here are the details and how to reproduce:

  1. Start with the latest version of the Classic Editor, WP 5.0 beta, and the following mvp code snippet:
    class ClassicBoxTest {
      public static function init() {
        add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_box' ) );
      }
    
      public static function add_meta_box() {
          add_meta_box(
              'classic-box',
              'Classic Box',
              'ClassicBoxTest::classic_box_render',
              null, 'normal', 'high',
              array(
                '__block_editor_compatible_meta_box' => false,
            )
          );
      }
    
      public static function classic_box_render() {
        echo "Testing";
      }
    }
    ClassicBoxTest::init();
    
  1. When WP_DEBUG is false the box will render properly.
  1. When WP_DEBUG is true, you will get the following fatal error:
    Fatal error: Uncaught ReflectionException: Function ClassicBoxTest::classic_box_render() does not exist in /srv/www/woodev/wp-admin/includes/template.php:1100 
    Stack trace: 
    #0 /srv/www/woodev/wp-admin/includes/template.php(1100): ReflectionFunction->__construct('ClassicBoxTest:...') 
    #1 /srv/www/woodev/wp-admin/edit-form-advanced.php(714): do_meta_boxes(Object(WP_Screen), 'normal', Object(WP_Post)) 
    #2 /srv/www/woodev/wp-admin/post.php(179): include('/srv/www/woodev...') 
    #3 {main} thrown in /srv/www/woodev/wp-admin/includes/template.php on line 1100
    

In previous versions of WP the box would always render properly.

The error seems to be coming from the code block in wp-admin/includes/template.php lines 1096-1129 that only gets processed when WP_DEBUG is true and seems to be related to the ReflectionFunction class.

Let me know if you need any more info. Thanks!

Attachments (1)

45192.diff (729 bytes) - added by DrewAPicture 6 years ago.

Download all attachments as: .zip

Change History (7)

#1 @DrewAPicture
6 years ago

  • Component changed from General to Editor
  • Focuses administration added
  • Keywords needs-patch added

Here's the offending code in WooCommerce with the static method callback:

add_meta_box( 'woocommerce-product-images', __( 'Product gallery', 'woocommerce' ), 'WC_Meta_Box_Product_Images::output', 'product', 'side', 'low' );

We can pass CLASSNAME::methodname to ReflectionMethod, just need to specifically check for it. It does feel a bit icky, but I guess we could do an elseif checking for :: in the callback string before falling back to ReflectionFunction() in the else.

Here is the core code in question::

<?php
if ( WP_DEBUG && ! $screen->is_block_editor() && ! isset( $_GET['meta-box-loader'] ) ) {
        if ( is_array( $box['callback'] ) ) {
                $reflection = new ReflectionMethod( $box['callback'][0], $box['callback'][1] );
        } else {
                $reflection = new ReflectionFunction( $box['callback'] );
        }

        // Don't show an error if it's an internal PHP function.
        if ( ! $reflection->isInternal() ) {

                // Only show errors if the meta box was registered by a plugin.
                $filename = $reflection->getFileName();
                if ( strpos( $filename, WP_PLUGIN_DIR ) === 0 ) {
                        $filename = str_replace( WP_PLUGIN_DIR, '', $filename );
                        $filename = preg_replace( '|^/([^/]*/).*$|', '\\1', $filename );

                        $plugins = get_plugins();
                        foreach ( $plugins as $name => $plugin ) {
                                if ( strpos( $name, $filename ) === 0 ) {
                                        ?>
                                                <div class="error inline">
                                                        <p>
                                                                <?php
                                                                        /* translators: %s: the name of the plugin that generated this meta box. */
                                                                        printf( __( "This meta box, from the %s plugin, isn't compatible with the block editor." ), "<strong>{$plugin['Name']}</strong>" );
                                                                ?>
                                                        </p>
                                                </div>
                                        <?php
                                }
                        }
                }
        }
}

call_user_func($box['callback'], $object, $box);
Version 2, edited 6 years ago by DrewAPicture (previous) (next) (diff)

@DrewAPicture
6 years ago

#2 @DrewAPicture
6 years ago

  • Keywords has-patch added; needs-patch removed
  • Milestone changed from Awaiting Review to 5.0

Added 45192.diff.

#3 @pento
6 years ago

  • Owner set to pento
  • Resolution set to fixed
  • Status changed from new to closed

In 43830:

Meta Boxes: Fix error when a meta box is rendered with a static method callback.

When WP_DEBUG is set, ensure that a static method callback is passed to ReflectionMethod, instead of ReflectionFunction.

Props DrewAPicture.
Fixes #45192.

#4 @claudiulodro
6 years ago

Patch looks good to me and solves the issue in my testing. Thanks!

#5 @SergeyBiryukov
6 years ago

  • Keywords fixed-5.0 added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for trunk.

#6 @pento
6 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 44170:

Meta Boxes: Fix error when a meta box is rendered with a static method callback.

When WP_DEBUG is set, ensure that a static method callback is passed to ReflectionMethod, instead of ReflectionFunction.

Merges [43830] from the 5.0 branch to trunk.

Props DrewAPicture.
Fixes #45192.

Note: See TracTickets for help on using tickets.