Opened 4 years ago
Last modified 5 weeks ago
#54184 new defect (bug)
HTML entities get decoded in Customizer text fields
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | Awaiting Review | Priority: | normal |
| Severity: | normal | Version: | 5.8.1 |
| Component: | Customize | Keywords: | |
| Focuses: | ui, administration, coding-standards | Cc: |
Description
Part 1
- Use
WP_Customize_Manager::add_setting()andWP_Customize_Manager::add_control()to create atextsetting/control with the default value©; - Navigate to the newly added setting in the Customizer.
Expected Result
The literal text © is in the edit box (as specified for the default value).
Actual Result
A copyright symbol (©) is in the edit box.
Part 2
- Enter the text
&in the above edit box (replacing what was there); - Publish (save) settings;
- Reload the page and navigate to the setting once again.
Expected Result
The literal text & is in the edit box (as originally entered).
Actual Result
Only a single ampersand symbol (&) is in the edit box.
Note
Same results if the setting is given type textarea.
Whatever is entered into text controls, or provided for a default value, should be preserved as is. The WordPress Customizer has no knowledge of how it is going to be used and should not make presumptions that it is going to be used in HTML output.
Change History (5)
#2
@
6 weeks ago
Thank you for finally responding after 4 years.
Here is some code that exhibits the problem:
<?php \add_action( 'customize_register', function ($wpCustomize) { $wpCustomize->add_setting( 'test54184', [ 'default' => '©', ] ); $wpCustomize->add_control( 'test54184', [ 'label' => 'Test for #54184', 'type' => 'text', 'section' => 'title_tagline', ] ); } );
(Edited for code formatting - @jonsurrell)
#3
@
6 weeks ago
Replying to jonsurrell:
Does this happen with other HTML character references?
It happens with all valid HTML character references, including with decimal and hex notation.
#4
follow-up:
↓ 5
@
5 weeks ago
This seems like a case of the esc_attr() trying to avoid double-encoding entities around here:
WP_Customize_Control::render_content().
#60229 may someday help with this by introducing templating and the ability to distinguish between HTML and unescaped plaintext.
For this specific issue, a workaround may be to override ::render_content(), but swap any esc_attr() or esc_html() calls for a strtr() like the HTML API uses. This snippet is a suitable replacement for esc_attr() and esc_html() where escaping is intended (regardless of whether things appear to be double-escaped):
<?php $escaped_content = strtr( $plaintext_content, array( '<' => '<', '>' => '>', '&' => '&', '"' => '"', "'" => ''', ) )
This is the same issue as #64054, except that this issue is for the customizer.
#5
in reply to:
↑ 4
@
5 weeks ago
Replying to jonsurrell:
a workaround may be to override
::render_content(), but swap anyesc_attr()oresc_html()calls for astrtr()
Just calling htmlspecialchars() directly (rather than strtr()) would do the job. The esc_xxxx() functions indirectly do that, but pass false as the $double_encode parameter. I guess that behaviour is a hangover from WordPress having various strings floating around that have been HTML-encoded out-of-context.
Maybe simply adding $double_encode as an optional parameter to the esc_xxxx() functions (default false to maintain current behaviour by default) would be a fairly straightforward solution to allow correct escaping in situations where it is known that the string is not already HTML-encoded.
Thanks for the report! Does this happen with other HTML character references?
It would be helpful if you share a full working code example to test this out.