register_post_type_argsfilter-hookWP 4.4.0

Allows changing the arguments passed to register_post_type when any post type is registered. It fires before the default arguments are generated, merged with the supplied arguments, and applied.

All arguments passed through the register_post_type_args filter hook are documented on the register_post_type page.

Usage

add_filter( 'register_post_type_args', 'wp_kama_register_post_type_args_filter', 10, 2 );

/**
 * Function for `register_post_type_args` filter-hook.
 * 
 * @param array  $args      Array of arguments for registering a post type. See the register_post_type() function for accepted arguments.
 * @param string $post_type Post type key.
 *
 * @return array
 */
function wp_kama_register_post_type_args_filter( $args, $post_type ){

	// filter...
	return $args;
}
$args(array)
Arguments passed as the second parameter of register_post_type() when registering a new post type.
$post_type(string)
The post type name passed as the first parameter of register_post_type(), such as post, page, or product.

Examples

#1 Change "Posts" to "News"

A simple example of replacing "Posts" with "News" in the admin sidebar and admin bar.

add_filter( 'register_post_type_args', 'filter_register_post_type_args', 10, 2 );

function filter_register_post_type_args( $args, $post_type ) {

	if ( 'post' == $post_type ) {
		$args['labels'] = [
			'name'          => 'News',
			'singular_name' => 'News item',
		];
	}

	return $args;
}

Because only labels are changed here, this task is better handled with the dedicated post_type_labels_(post_type) filter. See a complete example here.

#2 Change the REST route for Posts

By default, Posts are available to REST requests at:

http://example.com/wp-json/wp/v2/post

If Posts are used to publish news, it makes sense to use a corresponding REST route, for example:

http://example.com/wp-json/wp/v2/news

To do this, change the rest_base argument when the Posts post type is registered:

add_filter( 'register_post_type_args', 'change_rest_base_posts', 10, 2 );

function change_rest_base_posts( $args, $post_type ) {
	if ( 'post' == $post_type ) {
		$args['rest_base'] = 'news';
	}

	return $args;
}

#3 Enable an archive page for Posts

This code has not been fully tested and is published only as an example of using the hook.

It works correctly with permalinks in the "Post name" form: http://example.com/sample-post/.

By default, enabling an archive page for posts requires creating a static page (post_type=page) and then selecting it under Settings → Reading. If this is inconvenient, use the following solution:

add_filter( 'register_post_type_args', 'change_register_post_type_args', 10, 2 );

function change_register_post_type_args ( $args, $post_type ) {
	if ( 'post' === $post_type ) {
		$args['has_archive'] = 'news'; // Archive slug
		$args['rewrite']     = true;
	}

	return $args;
}
Problem: incorrect link to the posts archive

get_post_type_archive_link() will return the site home page URL instead of my-site.com/news/. Use the post_type_archive_link filter to return the correct URL.

Solution:

add_filter( 'post_type_archive_link', 'post_type_archive_link__news', 10, 2 );

/**
 * @param string $link
 * @param string $post_type
 *
 * @return bool|string
 */
function post_type_archive_link__news( $link, $post_type ) {
	global $wp_rewrite;

	if ( $post_type === 'post' ) {
		$post_type_obj = get_post_type_object( $post_type );

		/** start @see get_post_type_archive_link() */
		if ( ! $post_type_obj->has_archive ) {
			return false;
		}

		if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) ) {
			$struct = ( true === $post_type_obj->has_archive ) ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;
			if ( $post_type_obj->rewrite['with_front'] ) {
				$struct = $wp_rewrite->front . $struct;
			} else {
				$struct = $wp_rewrite->root . $struct;
			}
			$link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
		} else {
			$link = home_url( '?post_type=' . $post_type );
		}
		/* end */
	}

	return $link;
}
Problem: no archive link in the admin panel

Unlike custom post types, Posts have no link to their front-end archive in the admin bar. Use the admin_bar_menu hook to add the required menu item to the admin bar.

Solution:

add_action( 'admin_bar_menu', 'admin_bar_add_archive_post_link', 100 );

/**
 * @param WP_Admin_Bar $wp_admin_bar
 */
function admin_bar_add_archive_post_link( $wp_admin_bar ) {
	if ( is_admin() && is_post_type_archive( 'post' ) ) {
		$wp_admin_bar->add_menu( [
			'id'    => 'archive_post_link',
			'title' => 'View News',
			'href'  => get_post_type_archive_link( 'post' ),
		] );
	}
}

#4 Include the product post type when deleting a user

Suppose the registered product post type has delete_with_user set to false, meaning the user's posts should not be removed when the user is deleted. Change this behavior through the hook so the user's product posts are deleted with the user.

add_filter( 'register_post_type_args', 'register_post_type_product_args', 10, 2 );

function change_rest_base_posts( $args, $post_type ) {
	if ( 'product' === $post_type ) {
		$args['delete_with_user'] = true;
	}

	return $args;
}

The same result can be achieved with post_types_to_delete_with_user:

add_filter( 'post_types_to_delete_with_user', 'add_post_type_product_to_delete_with_user', 10, 2 );

function add_post_type_product_to_delete_with_user( $post_types_to_delete, $id ){
	$post_types_to_delete[] = 'product';

	return $post_types_to_delete;
}

Changelog

Since 4.4.0 Introduced.

Where the hook is called

WP_Post_Type::set_props()
register_post_type_args
wp-includes/class-wp-post-type.php 502
$args = apply_filters( 'register_post_type_args', $args, $this->name );

Where the hook is used in WordPress

Usage not found.