Do WordPress widget (or sidebar) hooks exist? - wordpress

I'm trying to filter ALL widget output through a simple filter, but can't find any hooks and was hoping to be pointed in the right direction. Or possibly my efforts are not even possible?
My simple filter is something like this:
function clean_widget_output( $input ) {
return str_replace( array( "\t", "\n", "\r" ), '', $input );
}
add_[FILTER OR ACTION]( 'need_a_hook', 'clean_widget_output', 99 );
Any ideas? I'm pretty new to PHP, but I can get around.

This was borne out of the need/desire to clean the god-awful HTML spewed by WordPress' widgets. I love what they do, but some of the output makes me cry.
The short answer is output buffering because I couldn't find any widget or sidebar hooks.
The long answer is:
function tidy_sidebar( $sidebar_name_or_id )
{
ob_start();
$bool = dynamic_sidebar( $sidebar_name_or_id);
if ( $bool )
{
$str = ob_get_contents();
$str = 'do cleanup stuff...';
}
else
{
$str = '';
}
ob_end_clean();
return $str;
}
Then call echo tidy_sidebar( 'sidebar-name-or-id' ); from your theme.

I had a similar issue and after looking through Adam Brown's list of all WordPress filter hooks, found that the hook I needed does exist (widget_title, as pxl mentions), but that there is no hook to get all widget output. I thought I'd elaborate on the solution that worked for me.
Theoretically, the widget_title hook should affect all widgets on your blog, but I'm sure some 3rd party widgets neglect to include the necessary line of code to apply any title filters, so it's not foolproof. It worked for me, however, and it can be used to apply custom 'shortcode' (more accurately, in this case, 'longcode') or syntaxes to your widget titles. For example, I wanted to occasionally include html code in my widget titles, but by default, all html is stripped out. So, in order to be able to add things like <em> tags to text in some of my titles, I chose a custom syntax: [[ instead of < & ]] instead of > (for ex, [[em]] and [[/em]]) and then created a function in my theme's functions.php file to process that custom syntax and replace it with the html equivalent:
function parse_html_widget_title( $text ) {
return str_replace(array('[[', ']]'), array('<', '>'), $text);
}
Then I added a line below it to add the function as a filter:
add_filter('widget_title', 'parse_html_widget_title', 11); // 11 is one above the default priority of 10, meaning it will occur after any other default widget_title filters
The add_filter / apply_filter functionality automatically passes the content being filtered as the first parameter to the function specified as the filter, so that's all you need to do.
In order to do something similar for the main output of the widget, you would need to look at all your widgets to see what hook they use and verify that they have a filter for their main output, than use add_filter() for each hook you find with your custom callback function (for example, it's widget_text for the Text widget output, or get_search_form for the search form [you can see it in wp-includes/general-template.php, at the get_search_form() function]). The problem is that some of the dynamically generated widgets don't have hooks (like the Meta widget), which is why the output buffering solution Jeff provides is the most versatile, though not ideal, solution.

there are lots of hooks for wordpress widgets that aren't documented. The wordpress codex doesn't list them, for whichever reason (such as these hooks may change in the future and will break unexpectedly with new updates and versions)... so use these with extreme caution.
to find out what they are, there are at least 2 places to look:
<wordpress install directory>/wp-includes/default-filters.php
<wordpress install directory>/wp-includes/default-widgets.php
contained in those two files is a pretty good listing of all the hooks wordpress uses.
An example would be a filter for widgets is widget_title
again, use these with caution, they're not guaranteed to work past the specific version of the code you're looking at.

I'm not sure when they introduced the widget_text filter, maybe they didn't have it in '09 when this question was originally asked, but since it's there now, and for the sake of anyone that gets this stackoverflow like I did from google and just happens to read far enough down to see this answer, it's now actually quite simple:
function my_widget_filter( $content )
{
// manipulate $content as you see fit
return $content;
}
add_filter( 'widget_text', 'my_widget_filter', 99 );

Also maybe check out the dynamic_sidebar_params filter --
Another link --

Related

How bad is $wp_rewrite->flush_rules() on 'init' action hook?

According to the Codex:
[...] This function can be extremely costly in terms of performance. It should be used as sparingly as possible - such as during activation or deactivation of plugins or themes. Every attempt should be made to avoid using it in hooks that execute on each page load, such as init.
Ok, so, I know it shouldn't be used in every page load and I'm not, but I still need a very conditional rewrite rule on this project.
I have these 2 url structures:
- example.com/products/tables/fancy-computer-table //This is a product url, here I expect the normal behavior from wp.
- example.com/products/tables/office //This should be some kind of a filter, where the site gets all the tables related to the office department. Note how both URL structure matches.
To make it work, I narrowed it down to these very specific URLs, using some regex. If matched, I'll run 2 queries to verify if the url I'm in is for the filter I want that rule to apply, or if it's a product url. In the latter, I want wordpress to behave normally. But I have to flush the rules either way, whether it's a product or it's the category and the filter, so that both pages work properly and dinamically.
I do all this to narrow down the use of this function to the least possible, but the Codex doesn't really tell me how bad it does affect the performance, or why.
I'm passing the parameter on that function as false by the way, so it doesn't rewrite my htaccess file, but I'm not sure where that rewrite rule option is stored, if it's on the memory somewhere, or on the database, wish they would provide some clarification on that.
Thanks in advance for reading this question. Any pointers are appreciated here, even if you want to point me to some other way of doing this. :)
EDIT: Posting some code here so you guys can actually understand what I mean and let me know if this maybe this could be bad practice... maybe a suggestion on how to do it better.
<?php function custom_rewrite_products()
{
// regex to match either "products/tables/fancy-computer-table" or "products/tables/office"
preg_match('#products\/([^\/]+)\/([^\/]+)\/?#', $_SERVER['REQUEST_URI'], $url_matches);
if(is_array($url_matches)) {
$query_category = new WP_Query('category_name='.$url_matches[1]);
$query_category->get_posts();
$args = array(
'post_type' => 'filters',
'name' => $url_matches[2]
);
$query_post = new WP_Query($args);
$query_post->get_posts();
if($query_category->have_posts() && $query_post->have_posts()) {
$category_ID = '';
$filter = '';
$category_ID = '' . $query_category->query_vars['cat'] . '';
$filter = '' . $query_post->query_vars['name'] . '';
$string = "index.php?cat={$category_ID}&filter={$filter}";
add_rewrite_rule('products/([^/]+)/([^/]+)/?$', $string, 'top');
}
global $wp_rewrite;
//Call flush_rules() as a method of the $wp_rewrite object
$wp_rewrite->flush_rules(false);
}
}
add_action('init', 'custom_rewrite_products');
I still don't understand why, but the flush is needed here, so the $category_ID and $filter variables actually get passed to the rewrite rules. If I take it out, the rewrite just goes to the index page, the place where the values should be are empty.
In case you're wondering, I created the filters on a custom post type and they are related to each post by using a custom field, since they're like four or five and they're present on every category on this project. As you can see, I already have a category/subcategory structure and I didn't find it smart to create these filters once again by hand inside each main category.
There is a 'rewrite_rules' record in the 'wp_options' table that includes all the rewrite rules. When calling flush_rules(), WordPress will clear this record and regenerate all the new rules, including the ones you're not changing.

Wordpress plugin shortcode not working in page

I have create a custom plugin which create short code for some content, but when i used in a page it not display content it's show "[BhContent]" as normal text. code I'm using given below. Please anyone help me to short out this.
function bhavin_content(){
echo "Hello bhavin";
}
//[BhContent]
add_shortcode( 'BhContent', 'bhavin_content' );
Thanks in advance!
Take a look at the documentation here. You are supposed to return the content that is to be output, not output it yourself.
function bhavin_content(){
return "Hello bhavin";
}
add_shortcode( 'BhContent', 'bhavin_content' );
See this quote from the documentation:
Note that the function called by the shortcode should never produce output of any kind. Shortcode functions should return the text that is to be used to replace the shortcode. Producing the output directly will lead to unexpected results. This is similar to the way filter functions should behave, in that they should not produce expected side effects from the call, since you cannot control when and where they are called from.

Stop filtering WordPress function wp_insert_post

I have to make a few minor changes to a website built in WordPress, and I came across some problems with the wp_insert_content function. This function sanatizes input, taking some HTML tags completely out (like ) and deleting attributes on others. I would like to switch this off, and everywhere I find a link to http://pp19dd.com/2010/06/unfiltered-wp_insert_post/ where the solution is to add
'filter' => true
to the posts input array.
This article is from 2010 though, and from what I found an extra line was added in 2011 (http://web.archiveorange.com/archive/v/TDTh42SUwDEc1GFmSrvU). This line reads:
unset( $postarr[ 'filter' ] );
and is called right after merging the input with the defaults, and before sanitizing. It seems to me that this line cancels the 'filter' => true statement above. Indeed, sanitizing happens if the line is there, and disappears if the line is taken out.
So the easy solution would be to add the 'filter' => true and delete the extra line in the function. Problem though is that I have no idea where else the function is used, and I wonder if it's smart at all to hack right in the WP code. An update of WP would restore it anyway. So ... is there any other way to stop this function from sanitizing the input?
It is possible that some other plugin may be trying to sanitize the content, in such case remove all the filters is the only option, try the following:
remove_all_filters("content_save_pre");
$post_id = wp_insert_post($post);
Other possible filter tags are:
pre_content
pre_post_content
content_pre
Try them one by one also if it does not work.
i'm also in the process of importing posts with s in the content body.
i've been searching all morning for a solution, there have been some discussions on the topic. so far
kses_remove_filters();
has done nothing for me, neither did commenting these two lines:
unset( $postarr[ 'filter' ] ); // overrides 'filter' => true since 3.0 i guess
$postarr = sanitize_post($postarr, 'db');
in wp_insert_post() in post.php (defaults at line 2704).
there's another interesting bit at line 2874:
$data = apply_filters('wp_insert_post_data', $data, $postarr);
which seems like could be the source of our troubles, but i'm too much of a newbie to figure this out on my own.
really, truly, desperately need help! oh, and i can't comment, sorry for the spam action.
i would like to keep this thread open and find a solution.
I guess it worked before i posted, but the content i was importing already had HTML tags stripped
the easiest workaround would be to manually overwrite the content after inserting the post, but this only works for isolated environments or for importing
$wpdb->update($wpdb->posts, array("post_content"=>$content->content), array("ID"=>$postid), array("%s"), array("%d"));
anyhow,
remove_all_filters("content_save_pre");
did the trick!

how to change form action url for contact form 7?

I'm using Contact Form 7 in a wordpress site with multiple forms.
I need to direct one form to a different form action url than the others.
I found the reply below for a previous thread but I'm not sure how to go about it.
Can someone specify what exact code needs to be included in "additional settings"
and what the code in functions.php would look like?
Thanks for your help!
reply from diff. thread, which I don't completely understand...
*Yes, you have to change the "action" attribute in the form using this Filter Hook wpcf7_form_action_url. (what would be the code?) You could add the hook into your theme's functions.php and then just process the form data in your ASP page.(code?) *
Since you're not familiar with PHP code at all, I'll give you a bit of a crash course in coding within the Wordpress API.
First off, you need to know the difference between functions and variables. A variable is a single entity that is meant to represent an arbitrary value. The value can be anything. A number, somebody's name, or complex data.
A function is something that executes a series of actions to either send back - or return - a variable, or alter a given variable.
<?php
$a = 1; //Number
$b = 'b'; //String *note the quotes around it*
$c = my_function(); //Call to a function called my_function
echo $a; //1
echo $b; //b
echo $c; //oh, hello
function my_function()
{
return 'oh, hello';
}
?>
Wordpress utilizes its own action and filter system loosely based on the Event-Driven Programming style.
What this means is that Wordpress is "listening" for a certain event to happen, and when it does, it executes a function attached to that event (also known as a callback). These are the "Actions" and "Filters". So what's the difference?
Actions are functions that do stuff
Filters are functions that return stuff
So how does this all fit in to your problem?
Contact Form 7 has its own filter that returns the URL of where information is to be sent by its forms.
So lets look at the basics of a Filter Hook
add_filter('hook_name', 'your_filter');
add_filter is the function that tells Wordpress it needs to listen
for a particular event.
'hook_name' is the event Wordpress is listening for.
'your_filter' is the function - or callback - that is called when the 'hook_name' event is fired.
The link to the previous thread states that the hook name you need to be using is 'wpcf7_form_action_url'. That means that all you have to do is make a call to add_filter, set the 'hook_name' to 'wpcf7_form_action_url', and then set 'your_filter' to the name of the function you'll be setting up as your callback.
Once that's done, you just need to define a function with a name that matches whatever you put in place of 'your_filter', and just make sure that it returns a URL to modify the form action.
Now here comes the problem: This is going to alter ALL of your forms. But first thing's first: See if you can get some working code going on your own. Just write your code in functions.php and let us know how it turns out.
UPDATE:
The fact that you were able to get it so quickly is wonderful, and shows the amount of research effort you're putting into this.
Put all of this in functions.php
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url()
{
return 'wheretopost.asp';
}
As mentioned before, that will affect ALL of your forms. If this is only supposed to affect a form on a given page, you can do something like this:
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
global $post;
$id_to_change = 1;
if($post->ID === $id_to_change)
return 'wheretopost.asp';
else
return $url;
}
All you would need to do is change the value of $id_to_change to a number that represents the ID of the Post/Page you're trying to affect. So if - for example - you have an About Page that you would like to change the Action URL, you can find the ID number of your About Page in the Admin Dashboard (just go to the Page editor and look in your URL for the ID number) and change the 1 to whatever the ID number is.
Hope this helps you out, and best of luck to you.
Great answer #maiorano84 but I think you should check form ID instead of Post. Here is my version.
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
$wpcf7 = WPCF7_ContactForm::get_current();
$wpcf7_id = $wpcf7->id();
$form_id = 123;
return $wpcf7_id == $form_id? '/action.php' : $url;
}
Another thing you might need to disable WPCF7 AJAX. That can be disabled by placing the following code in your theme functions.php
apply_filters( 'wpcf7_load_js', '__return_false' );
You can add actions after a successful submission like the documentation says
Adding a filter will work in the sense that it will change the action on the form but unfortunately it will also break the functionality of the plugin. If you add the filter like other answers suggest the form will keep the spinner state after submission.
You can make the form do something else on submit by using advanced settings such as:
on_submit: "alert('submit');"
more details about advanced settings here.
According to #abbas-arif, his solution works great, but have a limitation. This solution change the form's action on all forms present in post with that ID.
A better solution should be to use directly the form's ID. To get it, whit wordpress >5.2, you can use:
add_filter('wpcf7_form_action_url', 'wpcf7_custom_form_action_url');
function wpcf7_custom_form_action_url($url)
{
$cf7forms = WPCF7_ContactForm::get_current();
$Form = $cf7forms -> id;
switch($Form){
case 1:
return 'destination like salesforce url 1...';
case 2:
return 'destination like salesforce url 2...';
case 3:
return 'destination like salesforce url 3...';
default:
return $url;
}
}

Wordpress the_category() reverse order so parents come first?

A template i'm using is calling the_category() to list the categories which a post belongs to. It's ordering them by default with the child name first then parents. Is there a way to reverse the order so that the categories are listed as Parent, Child, Second Child?
You could filter get_the_terms and modify the results to suit your needs. You will need to add or remove the filter or use a conditional to only modify this where you need it. Here is an example for reversing the order of the retrieved terms.
function reverse_categories($terms, $id, $taxonomy){
if($taxonomy == 'category'){
$terms = array_reverse($terms, true);
}
return $terms;
}
add_filter('get_the_terms', 'reverse_categories', 10, 3);
You can do this with a one-liner without creating a function/filter wherever you may implement get_the_category_list() function:
implode(', ',array_reverse(explode(',',get_the_category_list(','))))
Change the implode string to one of your choice if you don't want ", ".
I can personally confirm this works in WordPress 3.5 -- but i am sure it will work in just about any version of WordpPress since 1.5.2 when get_the_category_list() was introduced.

Resources