Tag Archives: Hook

Passing in a “from” header to wp_mail() does not work

I ran into an issue today where I was setting the “from” header in wp_mail(), but it didn’t show up when I received the email. The code looks like this:

1
2
$headers = 'From: Company <[email protected]>' . "\r\n";
wp_mail($email, $subject, $message, $headers);
$headers = 'From: Company <[email protected]>' . "\r\n";
wp_mail($email, $subject, $message, $headers);

I learned that the only reason my “from” header wouldn’t show up correctly is if one of the following filters overwrites it:

1
2
3
4
5
6
7
8
9
add_filter('wp_mail_from','custom_wp_mail_from');
function custom_wp_mail_from($email) {
  return '[email protected]';
}
 
add_filter('wp_mail_from_name','custom_wp_mail_from_name');
function custom_wp_mail_from_name($name) {
  return 'WordPress';
}
add_filter('wp_mail_from','custom_wp_mail_from');
function custom_wp_mail_from($email) {
  return '[email protected]';
}

add_filter('wp_mail_from_name','custom_wp_mail_from_name');
function custom_wp_mail_from_name($name) {
  return 'WordPress';
}

Most likely you have plugin enabled that uses the previous filters to overwrite the “from” header that is being passed into wp_mail().

You have two options to fix the issue:

  1. You disable the plugin that’s causing this.
  2. You overwrite the plugin’s filter by creating another filter right before calling wp_mail().

It would be a good practice for you to remove that filter upon sending the email, especially if you are creating a plugin that’s going to be used by an audience other than yourself. The reason for this is now apparent :).

You can do this via the remove_filter() function:

1
2
remove_filter('wp_mail_from','custom_wp_mail_from');
remove_filter('wp_mail_from_name','custom_wp_mail_from_name');
remove_filter('wp_mail_from','custom_wp_mail_from');
remove_filter('wp_mail_from_name','custom_wp_mail_from_name');

Important: WordPress notes the following:

To remove a hook, the function and priority arguments must match when the hook was added. This goes for both filters and actions. No warning will be given on removal failure.

So if you set a priority, be sure to match it. In my example above, I didn’t specify a priority, so the default of 10 was used.

WordPress get_post_type() doesn’t work when restoring a trashed post via undo

I have a custom post type that uses the following hook:

1
2
3
4
add_action(
    'untrash_post',
    array($this, 'custom_restore_function')
);
add_action(
	'untrash_post',
	array($this, 'custom_restore_function')
);

And the custom function looks as follows:

1
2
3
4
5
function custom_restore_function() {
    if(get_post_type() == 'custom_post_type') {
        $this->set_custom_post_type_display_status(1);
    }
}
function custom_restore_function() {
	if(get_post_type() == 'custom_post_type') {
		$this->set_custom_post_type_display_status(1);
	}
}

I have a very similar setup for custom_save_function, custom_trash_function, and custom_delete_function, and in all instances, get_post_type() works like a charm.

When you use the Trash action link to move a post to the trash, the link looks something like this:

post.php?post=118&action=trash&_wpnonce=910f2d7f30

And if you choose to restore that post from the trash screen via the Restore action link, it looks very similar:

post.php?post=118&action=untrash&_wpnonce=ddb4c9c68b

The problem is that when you trash a post and then decide to restore it again via the Undo link in the confirmation message, the custom_restore_function will fail.

The Undo link looks something like this:

edit.php?post_type=custom_post_type&doaction=undo&action=untrash&
ids=118&_wpnonce=ea0d2a97d2

And as you can see, the format is a bit different.

After doing more research and taking a closer look inside post.php to see what get_post_type() is actually doing:

1
2
3
4
5
6
7
8
9
10
function get_post_type($the_post = false) {
    global $post;
    if(false === $the_post)
        $the_post = $post;
    elseif(is_numeric($the_post))
        $the_post = get_post($the_post);
    if(is_object($the_post))
        return $the_post->post_type;
    return false;
}
function get_post_type($the_post = false) {
	global $post;
	if(false === $the_post)
		$the_post = $post;
	elseif(is_numeric($the_post))
		$the_post = get_post($the_post);
	if(is_object($the_post))
		return $the_post->post_type;
	return false;
}

It appears that $post doesn’t contain the post when using the Undo action link. I would be interested in knowing why?

Nevertheless, the easiest way to solve this problem was to modify the if statement to check for the post_type query string, which fortunately is available inside the custom_restore_function:

1
2
3
4
5
6
function custom_restore_function() {
    if(get_post_type() == 'custom_post_type'
    || $_GET['post_type'] == 'custom_post_type') {
        $this->set_custom_post_type_display_status(1);
    }
}
function custom_restore_function() {
	if(get_post_type() == 'custom_post_type'
	|| $_GET['post_type'] == 'custom_post_type') {
		$this->set_custom_post_type_display_status(1);
	}
}

WordPress hooks for saving, trashing, restoring, and deleting custom fields in a custom post type

This took me quite a while to figure out, but I finally determined what the proper hooks for managing custom fields in a custom post type in WordPress are.

In my scenario, I have a custom post type that uses the add_meta_box() function to add a few custom fields. As a matter of fact, those are the only fields available… the title, body, etc, have all been removed. Furthermore, I save those custom fields in a new table, because I need to perform additional actions outside of WordPress with that data, and storing them separately will make that a lot easier.

WordPress allows you to perform four actions with any post type, which meant I needed four hooks in order to keep the data in my table in sync with the status of the post. Those actions are: saving, moving something to the trash, restoring it from the trash, and permanently deleting.

It seems that WordPress is a bit inconsistent in the naming convention of those hooks, which is why it took some trial and error, but after spending some time with it, I’ve tested and confirmed the following four hooks to be the ones you need:

Saving

add_action('save_post', 'custom_save_function');

Trashing

add_action('wp_trash_post', 'custom_trash_function');

Restoring

add_action('untrash_post', 'custom_restore_function');

Deleting

add_action('delete_post', 'custom_delete_function');

Hooks that didn’t act the way I expected were: trash_post, wp_untrash_post, trash_custom-post-type, and untrash_custom-post-type. For instance, trash_post only worked with built-in post types, such as pages and posts, but save_post works even with custom post types.

Hopefully this two minute blog post will save someone some time, because those four hooks are pretty much necessary if you’re working with custom fields (unless you disable trash entirely and just permanently delete).