I’ve been steadily improving the Options Framework plugin these last several weeks and there’s several nice changes in this 0.6 release. The biggest new feature is sanitization filters and better validation, but there’s also a slew of other less noticeable code improvements.
Unfortunately, a couple things that worked in previous versions will break with this release unless theme code is updated. I debated these changes quite a bit but decided it was best to do this while the plugin is still relatively young and would affect the least amount of people.
Validation Filters
Validation filters are the most exciting update in the Options Framework. Not only is there better sanitization (read security), it’s also now possible to change the default validation on any input without hacking the plugin directly.
Several users had mentioned that they wanted to enter some html in the textareas. I updated this so $allowedtags can be used. But if you wanted a different sanitization method, the default can now be removed and a new one added in via your themes functions. (Edit: $allowedposttags might be used soon instead)
Since, “embed” is not one of the $allowedtags- here’s how you could remove the default santization from a text area and allow “embed” to be used:
/* * This is an example of how to override a default filter * for 'textarea' sanitization and use a different one. */ add_action('admin_init','optionscheck_change_santiziation', 100); function optionscheck_change_santiziation() { remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' ); add_filter( 'of_sanitize_textarea', 'of_sanitize_textarea_custom' ); } function of_sanitize_textarea_custom($input) { global $allowedtags; $of_custom_allowedtags["embed"] = array( "src" => array(), "type" => array(), "allowfullscreen" => array(), "allowscriptaccess" => array(), "height" => array(), "width" => array() ); $of_custom_allowedtags = array_merge($of_custom_allowedtags, $allowedtags); $output = wp_kses( $input, $of_custom_allowedtags); return $output; }
Allow Script and Embed Tags
A lot of folks have been asking how to include all the $allowedpsttags in addition to script and embed tags. Here’s how you would do it (hat tip Jake Caputo):
/* * This is an example of how to override a default filter * for 'textarea' sanitization and $allowedposttags + embed and script. */ add_action('admin_init','optionscheck_change_santiziation', 100); function optionscheck_change_santiziation() { remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' ); add_filter( 'of_sanitize_textarea', 'custom_sanitize_textarea' ); } function custom_sanitize_textarea($input) { global $allowedposttags; $custom_allowedtags["embed"] = array( "src" => array(), "type" => array(), "allowfullscreen" => array(), "allowscriptaccess" => array(), "height" => array(), "width" => array() ); $custom_allowedtags["script"] = array(); $custom_allowedtags = array_merge($custom_allowedtags, $allowedposttags); $output = wp_kses( $input, $custom_allowedtags); return $output; }
Checkbox Code Has Changed
The most noticeable change in version 0.6 is how checkbox data is stored. The reason it’s the most noticeable is because it’s the one most likely to break a current implementation. Instead of storing checkbox data as “true” or “false”, I’ve changed it to “1” or “0”, which is how WordPress itself stores checkbox values and much smarter way to do it. I’ve written about this more in another post called “Checkboxes and Booleans”.
If you currently are using checkboxes in your theme, you should update options.php to use a default value of “0” or “1”. You should also update how the theme reads checkbox data to something like:
if ( of_get_option('checkbox_option', "0") ) { do_action(); }
Helper Function Returns Boolean False by Default
Instead of having the helper function of_get_option return the string “false” by default, I’ve updated it to return the boolean false (thanks so a suggestion from @sawyerh). Again, there’s more about this in my post on booleans. This should just make it easier to check if options are saved in the database. This change isn’t likely to break something if it isn’t updated, but the new code for your theme should look like this:
if ( !function_exists( 'of_get_option' ) ) { function of_get_option($name, $default = false) { $optionsframework_settings = get_option('optionsframework'); // Gets the unique option id $option_name = $optionsframework_settings['id']; if ( get_option($option_name) ) { $options = get_option($option_name); } if ( !empty($options[$name]) ) { return $options[$name]; } else { return $default; } } }
Better Handling of Option Arrays
I updated the code for how arrays of options (like multicheckbox, background, and typography) are processed and stored. I don’t think should affect current users- but it’s something to keep an eye on. The new code allows the options to be stored directly into the array rather than having an additional step in the validation to process it.
Better Display of Messages
For anyone who dug into the code of 0.5, you probably saw my very awkward way of displaying the “Options Reset” and “Options Saved” messages. I had an option in the database for saving the message which was set when the form was submitted and then later cleared after the message was displayed.
By digging through WordPress core I found a more elegant way to do it. At the top of the options page I now use settings_errors(), which automatically displays any messages.
The messages are set in optionsframework_validate() as it processes the form. So, the reset message it now set like so:
// If the reset button was clicked if (!empty($_POST['reset'])) { // If options are deleted sucessfully update the error message if (delete_option($option_name) ) { add_settings_error('options-framework', 'restore_defaults', __('Default options restored.'), 'updated fade'); } }
Thanks and Credits
I owe a big thanks to Michael Fields for this release. He advised me on how to implement the validation filters and did a thorough code review which caught many of the html escaping errors. If you need a really solid WordPress developer to check your code, I’d highly recommend him.
I was only able to have a code review done thanks to several generous donations. Having cash to spend on a third party code check was extremely helpful, made the plugin much stronger, and was well spent! If you use the plugin and can contribute, a PayPal donation will make my day.
And finally, several people have been helping out with testing and development on GitHub. I really appreciate it! I’m probably leaving someone out, but big thanks to @mantone, @rejithomas, @sawyerh, @samargulies, @mfields, @adampickeringq, @djevrek, @utkarshkukreti, @celtic7, @helgatheviking, @johnraz, @jmilone, @thumbnet, and @pastorjack.
Update: Version 0.6 has been released
Great work Devin :-)
Is the theme version will also be updated ?
Yep. As soon as this is released I’ll start updating the theme version.
Thanks for mention @devin, and as always great work :)
great job devin! saw this got updated in my WP panels. and an update to portfolio press. seriously, how do you get so much done? geez.
also i think you gave me a shoutout, but you forgot the THE in my handle. @helgatheviking (although that isn’t actually my twitter handle and i just checked.. there is some OTHER person masquerading as helgatheviking. grumble.
Hi Kathy. I updated your handle. It only gets done because there is a lot of encouragement from folks using it. :)
just looking at all the filters now. very cool. but it seems that you’re still stuck using 1 type of sanitation for all inputs of the same type. for instance, what about leaving textareas as they are most of the time, but toggling off the validation only on specific textareas?
I left the $option variable in there so that you could do a conditional check against $option[‘id’]. You can check if its a certain id for specialize sanatization, otherwise return the default.
thought i was going to have to report an epic fail on my part, but it just clicked.
i think you have a typo above in your remove_filter. you don’t have a function called sanitize_text_field… both your function and filter are called of_sanitize_textarea. so your example wasn’t actually removing the filter for me.
you said you left $option in there, but it took me a while to figure out how to access it. in case anyone else needs to know, the key was that i needed to tell my add_filter to accept 2 arguments.
add_action('admin_init','optionscheck_change_santiziation', 100);
function optionscheck_change_santiziation() {
remove_filter( 'of_sanitize_textarea', 'of_sanitize_textarea' );
add_filter( 'of_sanitize_textarea', 'my_sanitize_textarea',10,2 );
}
function my_sanitize_textarea($input, $option) {
global $allowedtags;
if($option['validate'] == 'none'){
return $input;
} else {
$output = wp_kses( $input, $allowedtags);
return $output;
}
}
i’m probably going to leave my options array w/ the validate parameter = none anywhere i don’t care to validate… i think it will be a bit more “set it and forget it” than checking against the $option[‘id’]
thanks devin!
Hi Kathy. Text input does have a filter: add_filter( ‘of_sanitize_text’, ‘sanitize_text_field’ ). Check at the top of options-sanitize.php.
of_sanitize_textarea looks a bit confusing because it is applying the filter “of_sanitize_textarea” and then calling the function “of_sanitize_textarea”. To remove it and add your own you would do:
remove_filter( ‘of_sanitize_textarea’, ‘of_sanitize_textarea’ );
add_filter( ‘of_sanitize_textarea’, ‘custom_sanitize_textarea’, 10, 2 );
a little more progress. in lieu of not sanitizing at all, i found a good post on how to add items to your allowed tags. i figure once for accepting embeds and another time for allowing scripts, and i should be good.
function my_sanitize_textarea($input, $option) {
global $allowedtags;
if($option['validate'] == 'embed'){
$my_tags = array();
$my_tags = $allowedtags; //duplicate $allowed tags
$my_tags["iframe"] = array( //add new allowed tags
"src" => array(),
"height" => array(),
"width" => array(),
"frameborder" => array();
"allowfullscreen" => array();
);
$my_tags["object"] = array(
"height" => array(),
"width" => array()
);
$my_tags["param"] = array(
"name" => array(),
"value" => array()
);
$my_tags["embed"] = array(
"src" => array(),
"type" => array(),
"allowfullscreen" => array(),
"allowscriptaccess" => array(),
"height" => array(),
"width" => array()
);
$output = wp_kses( $input, $my_tags); //kses filter against my new list of allowed tags
return $output;
} else {
$output = wp_kses( $input, $allowedtags);
return $output;
}
}
is there a way i can make this on its own tab and change it so editors can have access to it? I usually set my clients up as editors and hide the appearance tab from them! :) thanks for such a great plugin.
BH
Not without customizing the plugin. The Options Framework Theme might be a better option if you need to make significant customizations.
If you’re unsure how to proceed it might be best to hire a developer. I can’t offer specific customization advice for this, though I will occasionally take on small freelance projects.
I’ve been doing extensive testing with v.0.6. It’s great work. One minor suggestion. Add a second “Save Options” button in the header of the options panel. I think it’s the way they have it set up in Canvas and it really helps usability (IMO) because the the most used options tend to be at the top of the page. Depending on how your options panel is set up, having to scroll to the bottom of the page every time can be a bit of a pain. A minor point but something to consider for a future update. Thanks again for the outstanding work.
Hey James. Your feature request is already being discussed and will likely make it into a future version: https://github.com/devinsays/options-framework-plugin/issues/43
If you’re doing a lot of testing, maybe you could load up the development version too: https://github.com/devinsays/options-framework-plugin. Could always use more help spotting bugs early.
Hey Devin, just downloaded the development version. Will let you know if I come up with anything. Thanks.
agree with james. something else i was going to try to take a stab at was having the panel “remember” which tab was last active after the save. if you’d been using the jquery UI tabs i’d know how to do that, but i’m less sure w/ your custom js.
Hi Devin,
Great plugin, have you considered adding a wysiwyg editor to the options? I’ve used it sometimes before it’s useful to customize say footer text to allow users to bold, underline text etc without using html tags.
Not planning to add a text editor, but you can set your text boxes to allow html tags and explain in the description how to use them.
Seems like the text editor has been added after all? It’s in the demo, but for some reason, paragraphs don’t work. Other tags are working fine (bold, links, etc). Any ideas?
Hi Gregg. A couple folks have reported this issue. I haven’t had a chance to track it down yet, but there is a ticket filed: https://github.com/devinsays/options-framework-plugin/issues/115
@gregg – this is what i usually do to handle the same situation for metaboxes. it ought to work w/ OF text editors too.
https://github.com/devinsays/options-framework-plugin/issues/115#issuecomment-6678701
What you did with this is a big contribution for me. I really appreciate you sharing it and as soon as I get a project that uses the framework I will donate.
thanks so much,
Paul
Great framework, mate.
I really can’t get HTML allowed in the text inputs, though.. I’ve tried absolutely everything with the code you’ve given above to remove the filter and add the new one.. for a start I’m not 100% sure where the code is supposed to go as it doesn’t say, but I’ve tried it now in every file in the framework folder as well as functions.php
I’ve tried some code from the comments, as well. I just cannot get the fields to allow and save HTML code.
:/
Okay so now I see this code does work for text fields, I can now save HTML to them.. but the paragraph above the code block says it’s for textareas which seems misleading? I’m assuming I can use the same code but tweak it to remove the filters from textareas, as well.
Again, thanks for a great options framework.
I should probably clarify that I’m looking to add tags to textareas – just saying HTML above was pretty vague as anchors tags and the like do work.
I updated the post to be a little more clear. I also realized that the sanitization is probably a little too tight here. I opened this ticket (https://github.com/devinsays/options-framework-plugin/issues/61) and will probably roll it out in the next release if there’s no objections.
Problem with IE7, your input radio and multicheck show all value in 1 field and the others don’t have any value. :)
Ug, IE7. Patches welcome! https://github.com/devinsays/options-framework-plugin
can we stop supporting IE7? if all the web devs out there we stop supporting it won’t people have to upgrade? :)
+1 Also, some of the biggest WP marketplaces out there already drop support for IE7, I think its time.
First, for the record, you’ve done a lot of great work with this framework and overall I give it a thumbs up! However…..with regards to the textarea, this still continues to be a major frustration because all of the tips and suggestions to allow pasting of code into the textarea is not working for me and I’ve tried many things as well. So for the theme I wanted to do, the google analytics code option is being stripped out, plus if someone wants to paste a php tag into the textarea (for example when using a slideshow plugin and wanting to add this to a part of a page), it gets stripped out totally. I’m not sure what the solution is for my situation, but in the mean time, I will have to scrap any options that lets a person paste code. I should note though, basic html seems to work ok, but javascript and php tags are stripped.
Did you follow the directions in the post? The code under the heading “Allow Script and Embed Tags” should allow you to use script and embed tags for your theme.
Hi Devin…yes, but to confirm, where am I pasting that code…just so I know I’m doing it in the right place? I tried a couple areas, in my functions.php and also the options-sanitize.php under the /* Textarea */ comment and I got errors, like this:
Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'custom_sanitize_textarea' was given in /mysite/html/proto/wp-includes/plugin.php on line 170
Warning: Cannot modify header information - headers already sent by (output started at /mysite/html/proto/wp-includes/plugin.php:170) in /mysite/html/proto/wp-includes/pluggable.php on line 934
Hi Devin, first off, I love the framework and it’s proved extremely usfull, however it’s been extremely frustrating trying to get HTML in any boxes. I’ve placed the code in every functions file I could find and I’ve had no luck.. Can you explain where EXACTLY it’s got to go? I’d be extremely grateful.
Many thanks.
It goes in the functions.php file of your theme. Or download the latest version of the plugin from GitHub (0.9). That allows most HTML tags in the textarea (embed and script will still need to be a conscious override).
Hello Devin, it’s a really great update and tutorials! Thanks! :D
However, error message appeared when i tried your ‘allow scripts tag’ snippet.
I think you should change the
$of_custom_allowedtags
variable into$custom_allowedtags
. A typo, i guess :)Thanks, you just saved someone else a headache.
Nice catch ….although, still not working for me as the field is stripped of it’s content when I click Save Options. HTML, PHP, etc., still not doable for me. I will have to forget about this one and have people manually paste their code in the theme files. Cheers!
Devin,
Check again your code in Allow Script and Embed Tags , you write
function custom_sanitize_textarea_custom($input)
it should befunction custom_sanitize_textarea($input)
:)Thanks. Updated.
Hey Devin,
Just had a real-world usecase for the sanitized text area (for adding in script/link tags to the header) which is awesome BTW!
One thing I’m running into is that it looks like when I introduce the sanitized function, I get the ‘Cheatin’ uh?’ message for user roles that do not have access to the main WP options screen I’m assuming. The entire theme options works fine, except for when I add these options in (which unfortunately effects the entire them options panel). Any advice on how to fix that? Thanks!
Great plugin Devin,
Just Like the others, I really get headache in “textarea”. It won’t render all of global html tags. It’s just only can render a few html tags. In my issue, I can/t include the “” tag. It’s really gave me frustration.
Hello, I tried to do this for link target, but it didn’t work.
$of_custom_allowedtags[“a”] = array(
“target” => array()
);
any idea about WYSIWYG implementation
It’s in the latest development version: https://github.com/devinsays/options-framework-plugin
Help me test it.
<form action="http://www.aweber.com/scripts/addlead.pl" method="post">
<input type="hidden" value="1" name="meta_message">
<input type="hidden" value="email" name="meta_required">
<input id="acpro_inp4" class="email" type="text" size="20" value="[email protected]" name="email">
<input id="" class="submit" name="submit" value="Submint">
</form>
I want to add above code in my textarea but i can’t. Could you help me? Thank!
Hi, I’m using a textarea (because editor does not work, does not show) and when I save the content the framework automatically strips all my HTML tags. I’m trying to include a but the sanitisers converts to plain text.
I have checked $allowedposttags an it shows and as allowed tags.
Any suggestion? Thanks in advance.
Thank you for the framework! Is there a way to allow element attributes using regular expressions? I need to allow data-[something]=”[value]”…
Is it just me, or are the sanitization filters no longer working? After upgrading to WP 3.5, the scripts I had used in a textarea are now displayed without any of the attributes; empty script tags. They worked previously.
Nothing was changed in the sanitization filters. Can you reproduce the issue?
Sorry, this seems to have been an issue on my end. I recently moved servers, and I think something got botched in the process. Seems to be all good now.
How can I allow any content in the textareas?
Thanks for your great work!
Add a custom filter that just returns in the input.
hi Devin, if i want set color link of theme? i have added to function.php
$link = of_get_option('a_color');
if ($link) {
echo ' a:link {color:'.$link['color'].'}';
}
and on file option.php
$options[] = array( "name" => "Link color",
"desc" => "Choose the link (a:link) color.",
"id" => "a_color",
"std" => "",
"type" => "color");
can you help me?
Is this still information still relevant?
The reason I am asking is that I had been playing around with the filters to allow HTML in a text area with the Options Framework Theme 1.6 and I couldn’t get it to work.
Then I integrated the options framework theme with the theme I have been working on and inputted HTML worked without adding any sort of filters. So, I was a bit perplexed. Thanks. Working with the Roots Theme.
Yes. It’s filtered by $allowedtags, so some html will work without any changes- just not embeds or script tags. See: https://github.com/devinsays/options-framework-plugin/blob/master/options-sanitize.php
i am using Options Framework Theme 1.4. when i am past adsense code it does not work. i am also try $allowedtags filter .
the > symbol gets changed to >
how do i get around this?
Hi Devin
Thank you for this great plugin.How can I use options.php in plugin folder?I mean I want to put options.php in plugin folder not in theme folder.Possible?
Possible, but you would definitely need to alter some paths and settings in the framework.
Hi Devin,
Im just trying to add input area into the theme options page where a user can place a url to outside website. Eg for facebook or twitter.
Chris
Text option doesn’t work?
Hi devin,
It works partly, but it puts the local web address before the outside website
The embed and script addition still didn’t work properly for async code for example! a lot of hassle!
I removed the sanitization for textarea completely (as stated here: http://nabtron.com/remove-textarea-sanitization-from-options-framework/8712/ )
Please let me know if it’s fine or should be updated in some way!
Instead of just returning the input, I’d perhaps check that the user has the capability to post unfiltered_html. You can removed the default textarea sanitization and use the of_sanitize_editor instead. See: https://github.com/devinsays/options-framework-plugin/blob/master/includes/class-options-sanitization.php#L122
Thanks Devin for your response and for code updation.
Hi Devin. Thanks for a great tool.
Do you have any idea how one might go about disabling all filtering of content inside tags in a textarea? CDATA comments in Javascript seem to cause the framework to strip out both the CDATA and the Javascript itself.
When i enter this in the textarea :
/**/
It gets changed to :
/**/
wait a minute … WordPress comments are stripping it out exactly the same way! what the…
If you want to use unfiltered HTML (like javascript), you’ll need to remove the default sanitization and use a custom one. Look at editor sanitization as an example.
How to allow ALL tags for textarea ? Thanks
Very Nice & easy to use plugin Devin, I have just one question that supposes I have created option for add social link, can I give an option to a user can easily add other social link fields thru dashboard they want and will show on the site?
I usually do social links by using the WordPress menus: https://wptheming.com/2014/08/social-menu-links/. I think that’s probably the best UI for it.