La versión WordPress 4.4 introdujo un nuevo filtro, el register_post_type_args, que permite modificar los argumentos de registro de un post type. Hasta ese momento se podía hacer por varios rodeos:

  1. Modificando la global $wp_post_types, con sus limitaciones y con la gran antipatía que las globales suelen generar.
  2. Utilizando el action registered_post_type que, por llegar después de que el post type se haya registrado, requiere rehacer el trabajo hecho previamente por register_post_type().
  3. Utilizando funciones específicas, como add_post_type_support(), que permiten modificar características concretas del post type.

Pero con el filtro register_post_type_args se pueden interceptar todos los argumentos antes de que el registro del post type tenga lugar. No hay limitaciones en las características a modificar ni trabajo que rehacer.

Entre los casos de uso discutidos en el ticket en el que se propuso este filtro (#17447), algunos de los más «evidentes» son la modificación de los labels o de las reglas de reescritura. Pero uno de los que más me llamó la atención, por buen ejemplo de la flexibilidad que aporta, fue la modificación de las capacidades asociadas a un post type.

Imaginaos que hay un plugin que utiliza un custom post type y que hace exactamente lo que necesitas. Es el plugin perfecto. Pero resulta que utiliza el argumento capability_type en su valor predeterminado: post. Y en tu web los que escriben posts en el blog y los que gestionan este post type son personal separado y se quiere impedir el acceso de unos y otros.

No tienes por qué hacer un fork del plugin y mantenerlo tú, tampoco tienes por qué modificar la global $wp_post_types y probablemente varios hooks para algo tan delicado como las capacidades de creación, modificación y eliminación de contenido. El filtro  register_post_type_args lo soluciona del tirón.

Por ejemplo, podemos crear un pequeño plugin que modifique el capability_type y que asigne los capacidades adecuadas a cada grupo de usuarios según necesitemos. Por ejemplo:

// Filtramos los argumentos para añadir
// nuestro capability_type
add_filter( 'register_post_type_args' , 'cyb_register_post_type_args', 10, 2 );
funcion cyb_register_post_type_args( $args, $post_type ) {

    if( 'mi_post_type' == $post_type ) {
        $args['capability_type'] = 'cap';
    }

    return $args;

}

// Añadimos las capacidades personalizadas, correspondientes
// al capability_type utilizado anteriormente, a los
// roles/usuarios que deseemos al activar el plugin
register_activation_hook( __FILE__, function () {
	
       // Some custom role
	$manager	= get_role('manager');
       // Admin role
        $administrator  = get_role('administrator');
	
	$manager_and_admin_caps = cyb_get_capabilities_map();
	
	foreach( $manager_and_admin_caps as $cap ) {
		$manager->add_cap( $cap );
		$administrator->add_cap( $cap );
	}

} );

// Retiramos las capacidades personalizadas de los
// roles/usuarios al desactivar el plugin
register_deactivation_hook( __FILE__, function () {
	
	$manager	= get_role('manager');
	$administrator  = get_role('administrator');
	
	$manager_and_admin_caps = cyb_get_capabilities_map();
	
	foreach( $manager_and_admin_caps as $cap ) {
		$manager->remove_cap( $cap );
		$administrator->remove_cap( $cap );
	}

} );

// Tan solo una función auxiliar de ejemplo
function cyb_get_capabilities_map() {

    return array(
		'delete_caps',
		'delete_others_caps',
		'delete_private_caps',
		'delete_published_caps',
		'edit_caps',
		'edit_others_caps',
		'edit_private_caps',
		'edit_published_caps',
		'publish_caps',
		'read_private_caps'
    );

}

Pero como digo, este es tan sólo un ejemplo de la flexibilidad que aporta este filtro. ¿Algún otro caso de uso que os resulte interesante y queráis compartir?