Opened 5 years ago
Closed 5 years ago
#48747 closed defect (bug) (fixed)
WP_Customize_Setting doesn't clean up after itself
Reported by: | jon81 | Owned by: | fgiannar |
---|---|---|---|
Milestone: | 5.4 | Priority: | normal |
Severity: | minor | Version: | 3.4 |
Component: | Customize | Keywords: | good-first-bug has-patch commit |
Focuses: | Cc: |
Description
I've been working on a child theme for twentytwenty, and needed to replace the sanitize_callback on one of the customize settings registered in the parent theme.
I figured I could just delete the setting and re-create it with my own callback:-
// child theme add_action( 'customize_register', function( $wp_customize ) { $wp_customize->remove_setting( 'header_footer_background_color' ); $wp_customize->add_setting( 'header_footer_background_color', array( 'default' => '#ffffff' 'sanitize_callback' => 'my_sanitize_callback', 'transport' => 'postMessage', ) ); }, 20 ); function my_sanitize_callback( $value ) { // sanitize $value return $value; }
.. but the $value in my callback was empty and I couldn't figure out why until I dug a little deeper. The callback set in the parent theme was still being called before my own callback.
WP_Customize_Setting has no destructor and doesn't remove the filters/actions added during it's construction, so my call to $wp_customize->remove_setting() was not removing the previous sanitize callback.
Attachments (3)
Change History (19)
#1
follow-up:
↓ 2
@
5 years ago
- Focuses template removed
- Keywords reporter-feedback added
- Version changed from 5.3 to 3.4
#2
in reply to:
↑ 1
;
follow-up:
↓ 3
@
5 years ago
Replying to dlh:
I'm not sure whether there's a historical reason that the
WP_Customize_Manager::remove_*()
methods don't attempt to remove any hooks associated with the removed constructs. @westonruter sorry for the ping, but do you know?
Hi! I think it's just because it's not a need that came up. I thought there was some ticket for it, but I couldn't find it.
It's not great that the constructor for WP_Customize_Setting
is calling add_filter()
right away. It would be better if those filters were added later once they would be used. Alas.
In any case, I suggest removing the filters. Assuming there is only a sanitize_callback
you can just do:
<?php remove_all_filters( 'customize_sanitize_header_footer_background_color' );
#3
in reply to:
↑ 2
@
5 years ago
Replying to dlh:
is there a reason the
customize_sanitize_{$id}
filter can't be used instead?
Hi! I did look into removing the filter manually, though I'd need to remove all filters as @westonruter mentioned above. I've also considered just creating a new setting as a proxy or replacing the twentytwenty customize_register
hook entirely.
Replying to westonruter:
In any case, I suggest removing the filters. Assuming there is only a
sanitize_callback
you can just do:
<?php remove_all_filters( 'customize_sanitize_header_footer_background_color' );
Thanks! I think this is what I may end up doing.
I imagine there isn't a great need for WP_Customize_Setting
to clean up, it was just a frustrating afternoon trying to figure out why remove_setting()
wasn't behaving as I expected.
#4
follow-up:
↓ 5
@
5 years ago
- Keywords dev-feedback has-patch added
I can understand why that would be frustrating, for sure. Thinking about it more, though, I wonder whether the current behavior is preferable given that an instance of WP_Customize_Setting
can be associated with more than one instance of WP_Customize_Manager
(see #40527.) Same goes for controls, sections, and panels. So, I'm not sure that removing a setting from one instance of a manager necessarily means the setting should be torn down.
I threw together 48747.diff as a possible change to provide a workaround: Returning the removed construct to the developer for further processing, such as removing hooks. I'm not sure I'm sold on it, though. It's harmless enough, but would it have been all that useful in your case, @jon81?
Perhaps instead we should call this maybelater
.
#5
in reply to:
↑ 4
;
follow-up:
↓ 6
@
5 years ago
Hey @dlh, to give a bit of context to what I was working on:-
I wanted to replace some of the color controls defined in the parent theme, with a control that supports rgba (Alpha Color Picker), I was coming unstuck with sanitize_hex_color
running before/instead-of my own sanitize callback.
The patch you suggested would make it easier to remove the sanitize filter, though I feel it's use would only be apparent after one has discovered the issue at hand. Now that I know what the problem is I can workaround it myself.
I think what Weston suggested would be the way to go if possible, have filters added when needed, rather than in the constructor.. that way I could presumable remove a setting in the customize_register
hook before any filters have been added.
#6
in reply to:
↑ 5
;
follow-up:
↓ 7
@
5 years ago
- Keywords needs-patch added; dev-feedback has-patch reporter-feedback removed
Replying to jon81:
I think what Weston suggested would be the way to go if possible, have filters added when needed, rather than in the constructor.. that way I could presumable remove a setting in the
customize_register
hook before any filters have been added.
True enough. But, it would come with some backwards-compatibility challenges, I think. For example, the remove_all_filters()
approach would no longer work as early in the Customize bootstrap process as it does now if the setting filters were added later.
How about, at least, describing this gotcha in the docs for the remove_*()
methods? I'm thinking it could say exactly what's in the ticket description: that removing a construct from a manager doesn't destroy the class instance or "tear down" its filters. Would you be interested in writing a patch for that, @jon81?
#7
in reply to:
↑ 6
@
5 years ago
Replying to dlh:
How about, at least, describing this gotcha in the docs for the
remove_*()
methods? I'm thinking it could say exactly what's in the ticket description: that removing a construct from a manager doesn't destroy the class instance or "tear down" its filters. Would you be interested in writing a patch for that, @jon81?
Absolutely, that sounds like a good idea to me!
#8
follow-up:
↓ 9
@
5 years ago
- Keywords good-first-bug added
- Owner set to jon81
- Status changed from new to assigned
Since the focus of this ticket for the time being is the docs update, marking this as a good-first-bug
and assigning it as "claimed."
@jon81, if it turns out you don't think you'll be able to upload a patch here, no worries at all. Just reply back and you'll be un-assigned.
#9
in reply to:
↑ 8
@
5 years ago
Hi @dlh,
Sorry for the late reply! I didn't realise you were waiting on me to write a patch, I'd prefer to be unassigned for the time being.. as I don't have any experience writing patches and I'm very busy leading up to the end of year, as are we all no doubt?
Thankyou for all your help, and I wish you the best in the coming holidays!
#10
@
5 years ago
- Owner jon81 deleted
No problem, @jon81. If you do get the urge to write the patch after all, the core handbook has great documentation on setting up a development environment and working with patches.
#11
@
5 years ago
- Keywords has-patch added; needs-patch removed
Hi there,
@dlh I uploaded a patch, trying to do exactly what you described.
Please note this is my first ticket ever, so any comments are more than welcome :)
#12
@
5 years ago
- Milestone changed from Awaiting Review to 5.4
- Owner set to fgiannar
Welcome @fgiannar, and thanks for the patch!
I made a couple of adjustments to reduce the line length of the comments and specify which class instances are being referred to. Also, when generating diffs using Git, be sure to use the --no-prefix
flag for compatibility with SVN checkouts. Otherwise, this looks great to me.
Assigning to mark the good first bug as "claimed." I'm hopeful that this can be included in 5.4.
#13
@
5 years ago
Thanks a lot for your feedback @dlh!
I was thinking maybe your git related advice on --no-prefix
could be also added in the corresponding documentation about creating patches.
Please let me know if I can provide any additional help!
Hi @jon81, and welcome to WordPress Trac! Thanks for the report.
Putting aside the behavior of
remove_setting()
for a moment: If the setting is being replaced to use a custom sanitizing callback, is there a reason thecustomize_sanitize_{$id}
filter can't be used instead?I'm not sure whether there's a historical reason that the
WP_Customize_Manager::remove_*()
methods don't attempt to remove any hooks associated with the removed constructs. @westonruter sorry for the ping, but do you know?