0

This theme I was handed from another dev company is littered with add_action/filter( 'hook/filter', create_function( '', 'return blah('blah')' ); We will be moving this site to a server running php 7.2.

I am wondering what's the appropriate method to remove these actions and filters. Or can I simply just copy and paste the /path/to/file in the child directory and know that this will be overwritten?

Here's an example

if ( ! function_exists( 'ot_register_theme_options_page' ) ) {

        function ot_register_theme_options_page() {

            /* get the settings array */
            $get_settings = _ut_theme_options();

            /* sections array */
            $sections = isset( $get_settings['sections'] ) ? $get_settings['sections'] : [];

            /* settings array */
            $settings = isset( $get_settings['settings'] ) ? $get_settings['settings'] : [];

            /* build the Theme Options */
            if ( function_exists( 'ot_register_settings' ) && OT_USE_THEME_OPTIONS ) {

                ot_register_settings(
                    [
                        [
                            'id'    => 'option_tree',
                            'pages' => [
                                [
                                    'id'              => 'ot_theme_options',
                                    'parent_slug'     => apply_filters( 'ot_theme_options_parent_slug', 'unite-welcome-page' ),
                                    'page_title'      => apply_filters( 'ot_theme_options_page_title', __( 'Theme Options', 'option-tree' ) ),
                                    'menu_title'      => apply_filters( 'ot_theme_options_menu_title', __( 'Theme Options', 'option-tree' ) ),
                                    'capability'      => $caps = apply_filters( 'ot_theme_options_capability', 'edit_theme_options' ),
                                    'menu_slug'       => apply_filters( 'ot_theme_options_menu_slug', 'ut_theme_options' ),
                                    'icon_url'        => apply_filters( 'ot_theme_options_icon_url', null ),
                                    'position'        => apply_filters( 'ot_theme_options_position', null ),
                                    'updated_message' => apply_filters( 'ot_theme_options_updated_message', __( 'Theme Options updated.', 'option-tree' ) ),
                                    'reset_message'   => apply_filters( 'ot_theme_options_reset_message', __( 'Theme Options reset.', 'option-tree' ) ),
                                    'button_text'     => apply_filters( 'ot_theme_options_button_text', __( 'Save Changes', 'option-tree' ) ),
                                    'screen_icon'     => 'themes',
                                    'sections'        => $sections,
                                    'settings'        => $settings,
                                ],
                            ],
                        ],
                    ]
                );

                // Filters the options.php to add the minimum user capabilities.
                add_filter( 'option_page_capability_option_tree', create_function( '$caps', "return '$caps';" ), 999 );

            }

        }

    }

I'm aware the appropriate add_filter would come out to being add_filter( 'option_page_capability_option_tree', function($caps) { return $caps; }, 999);

1

2 Answers 2

1

In order to remove the hooks and filters, we need to be able to get a reference to the callable that was added, but in this case, create_function was used, so that's extremely difficult. It's also the reason you're getting deprecation notices. Sadly the only way to fix those deprecations is to change the parent theme to fix it.

Fixing The Deprecations

The PHP docs say that create_function works like this:

string create_function ( string $args , string $code )

Creates an anonymous function from the parameters passed, and returns a unique name for it.

And of note, create_function is deprecated in PHP 7.2

So this:

create_function( '$a', 'return $a + 1;' )

Becomes:

function( $a ) {
    return $a + 1;
}

Or even

function add_one( $a ) {
    return $a + 1;
}

This should eliminate the create_function calls, and turn the anonymous functions into normal calls that can be removed in a child theme

Removing The Hooks and Filters

Now that we've done that, we can now remove and replace them in the child theme.

To do this, we need 2 things:

  • to run the removal code after they were added
  • to be able to unhook the filters/actions

Putting your replacement in is easy, just use add_filter and add_action, but that adds your version, we need to remove the parent themes version.

Lets assume that this code is in the parent theme:

add_filter('wp_add_numbers_together' 'add_one' );

And that we want to replace it with a multiply_by_two function. First lets do this on the init hook:

function nickm_remove_parent_hooks() {
    //
}
add_action('init', 'nickm_remove_parent_hooks' );

Then call remove_filter and add_filter`:

function nickm_remove_parent_hooks() {
    remove_filter( 'wp_add_numbers_together' 'add_one' );
}
add_action( 'init', 'nickm_remove_parent_hooks' );
add_action( 'wp_add_numbers_together', 'multiply_by_two' );

Keep in mind that child themes let you override templates, but functions.php is not a template, and child themes don't change how include or require work. A child themes functions.php is loaded first, but otherwise, they're similar to plugins.

And Finally

You shouldn't be registering post types, roles, capabilities, and taxonomies in a theme, it's a big red flag and creates lock in, preventing data portability. These things are supposed to be in plugins, not themes

9
  • Unhooking these from WordPress filters and actions is not a generic PHP question. Dec 21, 2018 at 0:02
  • @JacobPeattie you misunderstand, the OP doesn't want to unhook them, the OP wants to replace them with versions that don't generate deprecation warnings, that's what my answer does. Moving beyond my answer would involve generic PHP callable knowledge though, hence the final paragraph, it's not the job of this stack to explain how to write a PHP closure, and there are other questions and answers for how to use hooks and filters with classes etc
    – Tom J Nowell
    Dec 21, 2018 at 0:54
  • They asked about removing them from a child theme. So they'd need to unhook them to do that. Dec 21, 2018 at 0:56
  • @JacobPeattie, re-read the original question, the OP wanted to add not remove, and the OP wanted to remove deprecation warnings in debug.log. How do they remove the create_function stuff that litters the theme they inherited, and add it so that there are no deprecations and the hooks can be used from the child theme? Right now that's not possible because of create_function and anonymous functions, hence my answer. The OP never asked how to unhook ( unhook != remove, one involves a remove_action call, the other involves code changes )
    – Tom J Nowell
    Dec 21, 2018 at 0:58
  • They didn't use the word "unhook", sure, but "method to remove these actions and filters and properly add them in a child theme" describes the very common and normal process of unhooking actions via a child theme and re-adding them. From the context of the question, including the mention of a child theme, it seemed apparent to me that editing the original theme was not what they are attempting to do. Dec 21, 2018 at 1:29
0

So turns out taking the following, and just removing if ( ! function_exists( 'ot_register_theme_options_page' ) ) { } and adjusting the filter will take priority over the parent theme.

if ( ! function_exists( 'ot_register_theme_options_page' ) ) {

    function ot_register_theme_options_page() {

        /* get the settings array */
        $get_settings = _ut_theme_options();

        /* sections array */
        $sections = isset( $get_settings['sections'] ) ? $get_settings['sections'] : [];

        /* settings array */
        $settings = isset( $get_settings['settings'] ) ? $get_settings['settings'] : [];

        /* build the Theme Options */
        if ( function_exists( 'ot_register_settings' ) && OT_USE_THEME_OPTIONS ) {

            ot_register_settings(
                [
                    [
                        'id'    => 'option_tree',
                        'pages' => [
                            [
                                'id'              => 'ot_theme_options',
                                'parent_slug'     => apply_filters( 'ot_theme_options_parent_slug', 'unite-welcome-page' ),
                                'page_title'      => apply_filters( 'ot_theme_options_page_title', __( 'Theme Options', 'option-tree' ) ),
                                'menu_title'      => apply_filters( 'ot_theme_options_menu_title', __( 'Theme Options', 'option-tree' ) ),
                                'capability'      => $caps = apply_filters( 'ot_theme_options_capability', 'edit_theme_options' ),
                                'menu_slug'       => apply_filters( 'ot_theme_options_menu_slug', 'ut_theme_options' ),
                                'icon_url'        => apply_filters( 'ot_theme_options_icon_url', null ),
                                'position'        => apply_filters( 'ot_theme_options_position', null ),
                                'updated_message' => apply_filters( 'ot_theme_options_updated_message', __( 'Theme Options updated.', 'option-tree' ) ),
                                'reset_message'   => apply_filters( 'ot_theme_options_reset_message', __( 'Theme Options reset.', 'option-tree' ) ),
                                'button_text'     => apply_filters( 'ot_theme_options_button_text', __( 'Save Changes', 'option-tree' ) ),
                                'screen_icon'     => 'themes',
                                'sections'        => $sections,
                                'settings'        => $settings,
                            ],
                        ],
                    ],
                ]
            );

            // Filters the options.php to add the minimum user capabilities.
            add_filter( 'option_page_capability_option_tree', create_function( '$caps', "return '$caps';" ), 999 );

        }

    }

}
1
  • That's not how that works. the child themes functions.php is loaded first, so this function gets defined first. Then, when the original code is run next, the function already exists, and since the function only gets defined if the function doesn't exist, it isn't defined. Nothing to do with child themes, just generic PHP. Note that this doesn't resolve PHP deprecation issues either
    – Tom J Nowell
    Dec 21, 2018 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.