WordPress.org

Make WordPress Core

Opened 4 years ago

Last modified 3 months ago

#17447 new enhancement

Add 'register_post_type_args' hook

Reported by: mikeschinkel Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version: 3.1
Component: Posts, Post Types Keywords: has-patch dev-feedback needs-docs
Focuses: Cc:

Description

I have two different use cases where I ideally would be able to hook the register_post_type() function:

  1. To add custom attributes and custom 'supports' values; current hooks don't allow adding support at the right time to be fully robust.
  1. To disable the default rewrite logic in order to support customized rewrite logic passed as custom attributes.

I've attached a patch that adds 'pre_register_post_type' and 'register_post_type' hooks to register_post_type().

Attachments (11)

register_post_type_hook.diff (722 bytes) - added by mikeschinkel 4 years ago.
Adds 'pre_register_post_type' and 'register_post_type' hooks to register_post_type().
register_post_type_args-hook.diff (627 bytes) - added by mikeschinkel 3 years ago.
register_post_type_args-hook-v2.diff (2.3 KB) - added by MikeSchinkel 15 months ago.
Revised 'register_post_type_args' based on current trunk and with hook documentation.
register_post_type_args-hook-v2.2.diff (2.4 KB) - added by MikeSchinkel 15 months ago.
Revised 'register_post_type_args' based on current trunk and with hook documentation.
register_post_type_args-hook-v2.3.diff (2.3 KB) - added by MikeSchinkel 15 months ago.
Fixed tabs (hopefully)
register_post_type_args-hook-v3.0.patch (788 bytes) - added by nickciske 15 months ago.
Allows filtering of all args for custom types, but only label filtering for _builtin types.
patch_commit_7407597a15e3.patch (878 bytes) - added by nickciske 15 months ago.
Cleaned up (formatting & style) -- allows filtering of all args for custom types, but only label filtering for _builtin types.
register_post_type_args-hook-v4.diff (4.9 KB) - added by MikeSchinkel 15 months ago.
Trying different and very granular approach
register-post-type-args-filter.17447.diff (967 bytes) - added by engelen 12 months ago.
Coarse-grained approach to filtering the arguments to register_post_type
register-post-type-args-filter.17447.v2.diff (967 bytes) - added by engelen 12 months ago.
Coarse-grained approach to filtering the arguments to register_post_type, which the filter applied before parsing with default arguments
register-post-type-args-filter.17447.v3.diff (967 bytes) - added by engelen 12 months ago.
Coarse-grained approach to filtering the arguments to register_post_type, which the filter applied before parsing with default arguments

Download all attachments as: .zip

Change History (44)

@mikeschinkel4 years ago

Adds 'pre_register_post_type' and 'register_post_type' hooks to register_post_type().

comment:1 follow-up: @scribu4 years ago

current hooks don't allow adding support at the right time to be fully robust.

Could you describe that in more detail? In other words, what's wrong with add_post_type_support() ?

comment:2 in reply to: ↑ 1 @mikeschinkel4 years ago

Replying to scribu:

what's wrong with add_post_type_support() ?

Red-faced, didn't know about add_post_type_support().

However, that function doesn't allow someone to intercept all $args passed to register_post_type() and change some of them before the register_post_type() operates on the $args. One example would be to set $args->rewrite = false; for all post types using a pre_register_post_type hook, and then define the rewrites differently using the register_post_type hook; this is exactly something I need right now for a project I'm working on.

A plugin developer may want to provide alternate rules for post type archives so it might want to set $args->has_archive = false; using a pre_register_post_type hook, and then define the post type archives differently using the register_post_type hook. This is also something I need.

In addition a plugin developer may want to provide an admin console option that allows the end user to define all the visibility settings for the different post types; a pre_register_post_type hook would enable that.

Another example is$args->columns which would include a keyed array of headers and callbacks and/or $args->column_headers containing an array of headers and $args->column_callbacks containing an array of callbacks. And yet another example would be to add $args->meta_boxes which would include a keyed array of meta_box args.

As stated, some of those examples are ones I currently would like to be able to streamline by specifying in the register_post_type()` call making it easier to define a full-features custom post type, and some of these examples of trying to keep WordPress from doing work to create data that is simply going to be thrown away.

Version 1, edited 4 years ago by mikeschinkel (previous) (next) (diff)

comment:3 @mikeschinkel3 years ago

  • Cc mikeschinkel@… added
  • Keywords 2nd-opinion added

I'm bumping into the need for this again, and would love to get this reviewed? Please?

comment:4 @mikeschinkel3 years ago

Bumping again? Please? I could really, really use this in 3.5...

comment:5 @nacin3 years ago

I thought we had these already. Must have gotten added elsewhere:

do_action( 'registered_post_type', $post_type, $args );

comment:6 follow-up: @SergeyBiryukov3 years ago

registered_post_type and registered_taxonomy were added in [18833].

comment:7 in reply to: ↑ 6 ; follow-up: @mikeschinkel3 years ago

  • Summary changed from Add register_post_type and pre_register_post_type hooks to Add 'register_post_type_args' hook

Replying to SergeyBiryukov:

registered_post_type and registered_taxonomy were added in [18833].

Those are great, thanks.

But the real reason for my request here is the get hook-based access to the args so I'm going to change the title of this ticket and to add the patch I'd like to see.

This patch would allow a plugin to disable some of the the default processing in register_post_type() and replace it with its own.

comment:8 @scribu2 years ago

#22818 was marked as a duplicate.

comment:9 in reply to: ↑ 7 @Jesper8002 years ago

Replying to mikeschinkel:

Replying to SergeyBiryukov:

registered_post_type and registered_taxonomy were added in [18833].

Those are great, thanks.

But the real reason for my request here is the get hook-based access to the args so I'm going to change the title of this ticket and to add the patch I'd like to see.

This patch would allow a plugin to disable some of the the default processing in register_post_type() and replace it with its own.

I agree: plugin authors need to be able to edit post type arguments on registering them. Currently, the only way to do it is by directly accessing $wp_post_types (come to think of it, get_post_type_object() should also work), which is not only undesirable but also quite inconvenient.

As far as your diff-file is concerned: the second one seems partially right. Naming the filter 'register_post_type_args' complies with the standards, and all necessary parameters are passed.

However... I'm wondering whether or not it would be better to apply the filter before calling wp_parse_args. That way, you make sure that all values required for registering a post type are present. This is different from what the standard is for filtering arguments when fetching data, but in this case we're actually creating a post type object that has to have certain properties, as people (and WordPress) expect them to be there, e.g. the post type labels.

If we call the filter before wp_parse_args we make sure that all required properties are available.

Returning false on empty( $args ) is definitely not the way to go, a WP_Error should be returned in that case.

comment:10 @Jesper8002 years ago

  • Cc jeve0@… added

comment:11 @jdgrimes15 months ago

I couldn't believe that there wasn't a filter here. There are times it would be really useful. What needs to happen to get this committed?

comment:12 @helgatheviking15 months ago

I also needed this today. Isnt' do_action( 'registered_post_type', $post_type, $args ); too late? You are required to re-do some of the processing that register_post_type() does instead of modifying the $args at the beginning of the function.

comment:13 @SergeyBiryukov15 months ago

  • Milestone changed from Awaiting Review to 3.9

comment:14 @DrewAPicture15 months ago

  • Keywords needs-docs added

Will need hook docs for this.

comment:15 follow-up: @nacin15 months ago

I'm not sure I like this proposal. A more detailed justification and explanation would be in order. Letting this function be "pluggable" could make post types even more fragile than they are already, given this is a still slowly evolving API.

@MikeSchinkel15 months ago

Revised 'register_post_type_args' based on current trunk and with hook documentation.

comment:16 in reply to: ↑ 15 @MikeSchinkel15 months ago

Replying to nacin:

A more detailed justification and explanation would be in order.

Here are the use-cases I've identified from prior projects:

  • Change the values for menu/post type visibility or just disable post types provided by a plugin/theme that are not needed for a specific site.
  • Add new plugin/theme specific "supports" for default post types and custom post types that don't explicitly specify supports.
  • Add new plugin/theme specific values to support plugin/theme added features. For example, 'my_exporter' value could be set to information that the My Exporter plugin uses to implement an export such as columns to include, column labels, WP_Query args for default export as well as meta fields to include.
  • Disable default rewrite rule addition so customized rewrite rules could be added in a function called for the 'registered_post_type' hook.
  • Disable default metabox callback registration so customized metabox callback registration could be performed in a function called for the 'registered_post_type' hook.
  • Disable taxonomy registration for object so customized taxonomy registration for object could be performed in a function called for the 'registered_post_type' hook.

@MikeSchinkel15 months ago

Revised 'register_post_type_args' based on current trunk and with hook documentation.

comment:17 @MikeSchinkel15 months ago

Replying to nacin:

Letting this function be "pluggable" could make post types even more fragile than they are already

An alternate to adding this single hook would be to provide several smaller hooks; one for each of the concerns I mentioned above so as:

  1. Short-circuit/disable selected post type registrations.
  2. Default supports
  3. Rewrite rules
  4. Metabox callbacks
  5. Taxonomy Registration

The first three are the ones I have found most need for.

BTW, I'd be interested in understand circumstances where allowing modification of $args would make post types more fragile. In Sunrise, we currently allow modification of $args via a hook in our wrapper function that calls register_post_type()so that a generic plugin can be used for many similar sites that need easy customization. If we are going to run into trouble with that I'd like to be able to anticipate what type of trouble.

@MikeSchinkel15 months ago

Fixed tabs (hopefully)

comment:18 @helgatheviking15 months ago

I've also needed to change some labels on post types registered by a plugin. This can be done by accessing the $wp_post_types global, but I think a filter would be more elegant.

comment:19 @nickciske15 months ago

+1

Here's my use case:

Using a 3rd party plugin that adds a CPT to WordPress... but the developer uses the built in 'post' capabilities -- which means it's difficult to have a user who can only edit that CPT (but not posts). It's easy for the dev and most plugin users, but doesn't use the WP capabilities system to allow the site owner to make those decisions.

In this case the 3rd party plugin had a filter wrapped around it's arguments before they were passed to register_post_type, but 99% of CPT plugins I've seen in the repo are not this considerate. Having this in core would be really useful to tweak 3rd party CPTs without having to fork the core plugin.

In addition, being able to change labels and other options while using a 'common' plugin (like Justin Tadlock's portfolio plugin) would increase standardization without hurting customizability. E.g., why fork the entire plugin just to rename them "Samples"?

As for fragility, anyone changing CPT arguments via a filter should know the risks - muck up the arguments and you'll break things, but that's the case with any core filter.

comment:20 follow-up: @nacin15 months ago

Thanks to both of you for some good examples. I don't think it's unreasonable to add the ability to modify a post type registration; I just wonder if a single one-size-fits-all hook makes the most sense. Keeping this more fine-grained might make things a little more verbose, but also a bit more stable. Not sold either way, just throwing out some ideas:

  • I'm not sure I love the idea of short-circuiting and preventing post type registration. I think we'd have to avoid this ability for built-in post types, at least for as long as WP falls flat on its face when this happens.
  • The ability to control labels should probably be its own discrete filter. If we make some changes, get_post_type_labels() might be usable in a callback to re-process as needed.
  • The ability to control the compiled capabilities should probably be its own discrete filter. If we make some changes, get_post_type_capabilities() might be usable in a callback to re-compile as needed.
  • There exists register_taxonomy_for_object_type(), unregister_taxonomy_for_object_type(), add_meta_box(), remove_meta_box(), add_post_type_support(), remove_post_type_support().
  • Rewriting and query variables could possibly be broken out.

comment:21 in reply to: ↑ 20 @MikeSchinkel15 months ago

Replying to nacin:

I don't think it's unreasonable to add the ability to modify a post type registration; I just wonder if a single one-size-fits-all hook makes the most sense. Keeping this more fine-grained might make things a little more verbose, but also a bit more stable.

Sounds reasonable to me.

How would you like to see us move forward with this so we might be able to consider patches for core sooner than later? New tickets for each use-case?

Any (other) specific direction regarding what you'd want to see/not want to see in patches?

comment:22 follow-up: @nickciske15 months ago

I for one never imagined this would apply to built in post types -- just post types added by plugins and (shudder) themes.

I'm not tied to a specific implementation -- more the idea that the plugin that registers a post type is not necessarily the final word and other plugins should be able to tweak/extend an already registered post type. The discrete approach sounds like more work but probably is the better route - filter the data upon "read" versus on "write".

I'd love to contribute to this - it would be my first "code" contribution to core ;-)

Last edited 15 months ago by nickciske (previous) (diff)

comment:23 @nacin15 months ago

I think new patches on this ticket is fine. I'm open to proposals. Let's experiment with some things and see where it takes up. Labels is easiest, capabilities a bit harder. I could also go for a "generic" filter if it bypasses things for built-ins. (Filtering labels are definitely OK for those, though.)

@nickciske15 months ago

Allows filtering of all args for custom types, but only label filtering for _builtin types.

@nickciske15 months ago

Cleaned up (formatting & style) -- allows filtering of all args for custom types, but only label filtering for _builtin types.

comment:24 in reply to: ↑ 22 @MikeSchinkel15 months ago

Replying to nickciske:

Nice first patch.

Several things.

  1. See DrewAPicture's comment about needing hook docs.
  2. Your patch doesn't allow short-circuiting of post type registration for non built-in types.
  3. Your patch doesn't pass in the sanitized version of the post type in $args['name'] and then capture it after the args as the post type name as in my v2.x of the patch so you wouldn't be able to modify a post type name in case of a conflict (which is mostly moot, but sometimes if the plugin to fix is trivial enough it might be workable.)

That said, I'm starting to think that it won't be as simple as just bypassing '_builtins'; for example one of your use-cases was the need to change capabilities; if we bypass builtins then capabilities for default post types can't be fine-tuned easily.

Maybe we should tackle each and every use-case instead of a more broad sweeping hook?

@MikeSchinkel15 months ago

Trying different and very granular approach

comment:25 @MikeSchinkel15 months ago

I just uploaded a new patch that is very different from the others that uses a granular approach to allowing arguments to be modified. It's not what I'd consider ready to apply to core but instead meant for discussion on the approach.

Last edited 15 months ago by MikeSchinkel (previous) (diff)

comment:26 @helen14 months ago

  • Milestone changed from 3.9 to Future Release

Sounds like this ticket is still exploring approaches, and unfortunately the time has come to punt enhancements from 3.9.

@engelen12 months ago

Coarse-grained approach to filtering the arguments to register_post_type

@engelen12 months ago

Coarse-grained approach to filtering the arguments to register_post_type, which the filter applied before parsing with default arguments

@engelen12 months ago

Coarse-grained approach to filtering the arguments to register_post_type, which the filter applied before parsing with default arguments

comment:27 @engelen12 months ago

Sorry about the patch overload, it took me some time to realize I hadn't committed my latest changes.

I would argue that the coarse-grained approach is desirable here. It gives developers full control over registered post types, and prevents a huge amount of filters being added. My most important argument, however, is that there are no post type arguments that should be usable when calling register_post_type but should not be modifiable by other plugins.

I've added a patch (a few, actually) that implements this: register-post-type-args-filter.17447.v3.diff. It implements the filter register_post_type_args, which filters the post type arguments.

  1. It applies the filter before calling wp_parse_args, which prevents removing required arguments via the filter (as any missing keys will simply be added via $defaults).
  2. The post type name is sanitized earlier on and passed to the filter as the second argument.
  3. The filter is only applied to non-built-in post types (i.e. custom post types, post types with _builtin false).

As far as post type labels are concerned: these are already filterable in register_post_type, as it calls get_post_type_labels which has been filterable (post_type_labels_{$post_type}) since 3.5.

@MikeSchinkel
I don't think the post type name should be filterable. The post type name is the unique identifier of a post type, which means changing it effectively means registering an altogether different post type. Furthermore, I don't see a problem with bypassing built-in post types altogether at this point, as it's just too fragile. Core and many plugins rely on the default, unfiltered settings from the default post types. Changing capabilities for these post types, for example, would break a lot of sites.

At this point, I think we should move ahead with adding this to core, as this is just about as lean and safe as it will get without losing control over custom post types.

Last edited 12 months ago by engelen (previous) (diff)

comment:28 @engelen11 months ago

  • Keywords 2nd-opinion removed

comment:29 @engelen10 months ago

I would really like to move forward with this ticket. Could somebody give a second opinion on this? I would love to see this in 4.0.

comment:30 @engelen7 months ago

Hmm. Bump?

comment:31 @SergeyBiryukov3 months ago

#31073 was marked as a duplicate.

comment:32 @teolaz3 months ago

Any new on this? I think there aren't trouble adding this filter, cause you could control every kind of post type adding the filter, so a dev could mod the post type args only if the post type isn't a built in one (for ex, you could control the $post_type on the register_post_type function, and this is only a method).

comment:33 @McGuive73 months ago

Bump. Would still love to see this one added to core. We use plugins like WP Types all the time which have their own method for registering custom post types. We often have the need to filter the rewrite slug, which would be way easy to do with a register_post_type() args filter.

Note: See TracTickets for help on using tickets.