WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 4 days ago

#12706 assigned task (blessed)

Custom post status bugs in the admin — at Version 129

Reported by: ptahdunbar Owned by: ptahdunbar
Milestone: Future Release Priority: normal
Severity: normal Version: 3.0
Component: Posts, Post Types Keywords: has-patch westi-likes needs-testing needs-refresh needs-unit-tests editorial-flow
Focuses: Cc:

Description (last modified by nacin)

A developer should be able to register a custom post status using register_post_status(). The admin UI (including post submit box and quick edit) should reflect this new custom post status. Furthermore, there are many hard-coded references to 'draft' and 'pending' statuses in core that should properly use the post status API.

All existing arguments to register_post_status() should be fully implemented, should also support per-post-type arguments. As things get implemented across core, there will likely be a need for supporting capabilities and bits of API.

Related: #23169 (register_post_status_for_object_type), #23168 (unregister_post_status).

Change History (134)

comment:2 @nacin5 years ago

  • Milestone changed from Unassigned to 3.0

comment:3 @sbressler5 years ago

  • Cc sbressler@… added

comment:4 @ptahdunbar5 years ago

  • Milestone changed from 3.0 to 3.1
  • Severity changed from blocker to normal

Don't have time for this so I'm pushing it back for 3.1 unless someone can tackle it :)

comment:5 @nacin5 years ago

  • Type changed from defect (bug) to enhancement

I don't see this as a bug. We simply never completed the API here.

Very similar to how we started custom post types in 2.9 then went through it with 3.1.

Moving to enhancement... Will probably end up as a task though.

comment:6 @johnkolbert5 years ago

  • Cc johnkolbert added

comment:7 @johnkolbert5 years ago

Just to let those know who are following this ticket, I just updated the diff file to this related trac ticket (http://core.trac.wordpress.org/ticket/12567) and would enjoy any feed back.

comment:8 @johnbillion5 years ago

  • Cc johnbillion@… added

comment:9 @kevinB5 years ago

  • Cc kevinB added

comment:10 @nacin5 years ago

  • Milestone changed from Awaiting Triage to 3.1
  • Type changed from enhancement to task (blessed)

Someone is free to start working on this before I get to it.

I want post statuses to be registered to a post type. That's one thing that gets me.

We also have like 18 properties but still need more based on things I noticed when trying to utilize what was there. So we should figure out a way to properly handle everything.

comment:11 @mikeschinkel5 years ago

  • Cc mikeschinkel@… added

comment:12 @andreasnrb5 years ago

  • Cc andreasnrb added

Think we need to do a write up of what the different options actually do.
Supposed difference between public, private, protected. _builtin and internal etc.
Public,private,protected makes custom post type with that status show up on its listings page.

The All(x) link always show the total count for the post type even with a unregistered post_status but the page display No post types found.

comment:13 @nacin5 years ago

#14318 was previously closed as a duplicate.

comment:14 @lumpysimon5 years ago

  • Cc piemanek@… added

comment:15 @ptahdunbar5 years ago

Alright, let's get this ticket moving. There's a few args in the current version of register_post_status that either make no sense, are redundant, or ones that I just don't understand and could use some clarification.

Here's the new params for the register function:

register_post_status( $post_status, $post_type, $args = array() );

Parameters:

  • $post_status (string) - Name of the post status.
  • $post_type (mixed) - string or array of post types to assign to the post status.
  • $args (array) - Optional.

Public args:

  • label - A descriptive name for the post status. Defaults to $post_status
  • label_count - Label used in the admin status links to display the post status' singular/plural count label. Defaults to label
  • post_type - An array containing post types this post status is associated with. Defaults to 'any'.
  • exclude_from_search - Whether to exclude posts with this post status from search results. Defaults to null.
  • public - Whether posts of this type should be shown in the admin UI. Defaults to null.
  • internal - Whether the post status is internal. Removes from any ui/query listing.
  • protected - User must have edit permissions on the draft to preview. Defaults to null.
  • private - Limited to viewing by the author of a post or someone who has caps to read private states. Defaults to null.
  • publicly_queryable - Whether post status queries can be performed from the front page. Defaults to null.
  • show_ui - Whether to show the post status in the admin UI. Defaults to null.
  • edit_cap: changing the post status can be limited by capability. If set, users must have the declared capability to change change posts to this post status. Defaults to null.

Internal args: (Used by WP core built-in post statuses)

  • _builtin - If this post status is a native or "built-in".

Args I left out: (can anyone explain the need for these?)

  • show_in_admin_all
  • show_in_admin_status_list
  • show_in_admin_all_list (uses show_ui instead)
  • single_view_cap
  • capability_type
  • hierarchical
  • _edit_link

Functions that (most likely) need updates:

  • get_available_post_statuses
  • wp_edit_posts_query
  • get_post_statuses
  • get_page_statuses
  • post_submit_meta_box

Files that need updates

  • edit.php:261
  • export.php:55,:132 (do we need a can_export arg?)
  • query.php:2234
  • script-loader.php & post.dev.js

See #12567

Thoughts?

comment:16 @wpmuguru5 years ago

There shouldn't be a separate function for page statuses. Pages are now just another post type other than WordPress needs to support features from when they were distinct.

The post type already has a can_export flag. The post status should depend on the post type flag for this. Though, this raises the issue of conditionally showing the post status on the export screen when it only applies to specific post types.

comment:17 @nacin5 years ago

get_page_statuses() is for back compat. I think get_page_statuses() and get_post_statuses() are only used in XML-RPC. They have hard-coded stati for that reason.

comment:18 follow-up: @kevinB5 years ago

Can we please default post_type to null? This is the standard approach for everything except the query variable, making

! empty ($status_obj->post_type)

sufficient to detect post_type customization in 3.0 and 3.1+

comment:19 in reply to: ↑ 18 ; follow-up: @ptahdunbar5 years ago

Replying to kevinB:

Can we please default post_type to null? This is the standard approach for everything except the query variable, making

! empty ($status_obj->post_type)

sufficient to detect post_type customization in 3.0 and 3.1+

The post_type param is required as your registering a post status to a post type. Defaulting to null means that the post status shouldn't register.

comment:20 in reply to: ↑ 19 ; follow-up: @kevinB5 years ago

Replying to ptahdunbar:

Replying to kevinB:

Can we please default post_type to null? This is the standard approach for everything except the query variable, making

! empty ($status_obj->post_type)

sufficient to detect post_type customization in 3.0 and 3.1+

The post_type param is required as your registering a post status to a post type. Defaulting to null means that the post status shouldn't register.

That breaks the API for plugins and themes which were written for WP 3.0. Why not make post_type part of the args array? Then calling code can associate the status with all post types if the property is defaulted null or not set.

comment:21 in reply to: ↑ 20 @kevinB5 years ago

Replying to kevinB:

Replying to ptahdunbar:

The post_type param is required as your registering a post status to a post type. Defaulting to null means that the post status shouldn't register.

That breaks the API for plugins and themes which were written for WP 3.0. Why not make post_type part of the args array? Then calling code can associate the status with all post types if the property is defaulted null or not set.

By calling code, I mean consumers of the resulting status object.

comment:22 @aesqe5 years ago

  • Cc aesqe@… added

@kevinB5 years ago

plugin to demonstrate custom stati "Approved" and "Secret". Corresponding roles of "Reviewer" and "Super Editor"

comment:23 @kevinB5 years ago

Just uploaded a patch for the first issue. This is mostly comprehensive, supporting use of the following type of stati:

  • private type, indicated by $status_obj->private. Some functionality as normal private, but a separate set of capability requirements which may include all or some of the following: "read_secret_posts", "edit_secret_posts", "delete_secret_posts", "set_secret_posts" (the "publish" equivalent). If a status-specific caps is not defined for some operation, the normal private status equivalent is used.
  • pending type, indicated by $status_obj->moderation. Enables additional multi-step moderation, optionally with status-specific capabilities. A new filter is applied to allow plugins to customize the default moderation status for the main Submit button:
$moderation_status = apply_filters( 'post_moderation_status', 'pending', $post->ID );

Remaining Issues:

  • I didn't touch xml-rpc or map_meta_cap (but see meta mapping in attached plugin for ideas)
  • Custom public stati now have some backend support but no Edit Form UI integration. The complication-to-benefit ratio seems much higher here; at this point I'm not eager to push it.
  • The js I moved into edit-form-advanced.php should be reviewed for optimal delivery method.
  • I don't know the WP way to compress js files. post.js and inline-edit-post.js in this patch are a copy of uncompressed dev.js

Demo Plugin:
I also attached a plugin to demonstrate two custom stati via the following roles:

  • "Reviewer" - has edit_approved, delete_approved, set_approved, edit_others, delete_others for all post types
  • "Super Editor" (name='super') - has read_secret, edit_secret, delete_secret, set_secret for all post types (in addition to regular editor caps)

The WP roles definitions will be added to your DB, but db-stored capabilities are only that of Contributor and Editor, respectively.

comment:24 @kevinB5 years ago

For the second issue (statuses should be registered to one or more post types), I suggest following the pattern set for taxonomies:

function register_taxonomy_for_object_type( $taxonomy, $object_type) {
	global $wp_taxonomies;

	if ( !isset($wp_taxonomies[$taxonomy]) )
		return false;

	if ( ! get_post_type_object($object_type) )
		return false;

	$wp_taxonomies[$taxonomy]->object_type[] = $object_type;

	return true;
}

I would be able to implement that type of solution early next week if nobody else has it done by then.

comment:25 @nacin5 years ago

Hi kevinB, for compressed scripts, only edit the .dev.js versions, and omit the compressed versions. We will then handle compression on commit.

I've asked Ptah to review this patch as I know he is also working on a patch, so let's see what we can grab from each to continue.

comment:26 follow-up: @ptahdunbar5 years ago

I'm thinking we should group the arguments into patches instead of writing up one big diff.

register_post_status() needs a labels arg for all of these:

  • name
  • count
  • caption
  • published (maybe a better wording?)
  • save_as (maybe a better wording?)

For the post_type arg, we need to be loop through the post_type arg and register_post_status_for_type()

  • post_type

There also needs to be a new post_status arg in register_post_type() that calls register_post_status_for_type(). If the post_status arg isn't passed, it registers all the builtin post statuses to that post type.

We'll need a post_type_has_status() (similar to what johnkolbert wrote in #12567) and use that throughout post_submit_meta_box() to turn features on/off.

I'm not exactly 100% sure on how public, private, and protected work in terms of what functionality they add outside of what's in the post_submit_meta_box() metabox.

  • public
  • private
  • protected
  • internal

And finally post status capability. Can anyone elaborate how this should work?

comment:27 in reply to: ↑ 26 ; follow-up: @kevinB5 years ago

Replying to ptahdunbar:

I'm not exactly 100% sure on how public, private, and protected work in terms of what functionality they add outside of what's in the post_submit_meta_box() metabox.

  • public
  • private
  • protected
  • internal

public stati are published and readable by default to all logged and anonyomous users (an abstraction of the "publish" status).

private stati are published but readable based on possession of the appropriate capability (an abstraction of the "private" status).

protected means a status is not currently readable to any user on the front end, except for previews.

internal means never readable on the front end, post are not set to it by "normal" wp-admin UI, and is not included in wp-admin post filtering unless specified (show_in_admin_status_list)

My patch includes another proposed status type:
moderation means a status is part of an editorial moderation process. Not readable on the front end, except for previews (an abstraction of the "pending" status).


And finally post status capability. Can anyone elaborate how this should work?

If the existing pattern is followed, capabilities for custom stati would be specified by setting

$type_object->cap->edit_{$status}_posts = ...
$type_object->cap->delete_{$status}_posts = ...


... and if the status is of private type:

$type_object->cap->read_{$status}_posts = ...

In addition, there is a need for a "publish" capability specific to custom public, private and moderation stati:

$type_object->cap->set_{$status}_posts = ...

If there is sentiment for a different model such that $type_obj->status_cap is a status-keyed array property, now is the time. Thoughts?

comment:28 in reply to: ↑ 27 @kevinB5 years ago

correction...

Replying to kevinB:

protected means a status is not currently readable to any user on the front end, except for previews.

internal means never readable on the front end, post are not set to it by "normal" wp-admin UI, and is not included in wp-admin post filtering unless specified (show_in_admin_status_list)

protected means not readable to any user on the front end, except for previews.

internal means not readable on the front end, posts are not set to it by "normal" wp-admin UI, and is not included in wp-admin post filtering unless specified (show_in_admin_status_list)

comment:29 @kevinB5 years ago

The updated patch also fixes some core bugs which may deserve their own ticket. I included them as part of this patch because my overall custom stati solution depends on the fix, or vice versa:

  • wp_list_filter() : 'or' argument does not work, always returns all members. This function is called by get_post_stati(), get_post_types() and get_taxonomies()
  • Users lacking publish capability can change an existing post of any status to Privately Published status via Quick Edit
  • On visibility or publish date change, js recaptions publish button as "Update Post" or "Update Page" (versus initial caption of "Update")

comment:30 @kevinB5 years ago

A few other anomalies I noticed:

1) Contributors can "edit" their own privately published posts, but saving throws it Pending Review status. I'm guessing this is not intended, and can address it as part of #14122 unless someone objects.

2) Contributors can save a post password to a Pending Post via Quick Edit, but not via the full edit form. The post remains in Pending Review status but retains the password if it is published. What is the intended behavior?

3) Setting the post date to future recaptions the publish button to "Schedule" if visibility is set public. But for private visibility, it retains the "Update" caption. Wouldn't it be better to show "Schedule" regardless of visibility - as a visual cue that the privately published post is about to be unpublished until the selected date?

comment:31 @kevinB5 years ago

I've scrutinized the patch quite extensively and believe it to be cleanly coded, logically consistent and functionally correct. If ptah, nacin and others have just not had time to look at it, no problem. But I'd like to know if you're seeing issues with it.

What else should I do to bring it toward commit eligibility? I know it seems like a big diff, but the changes all fit together toward the goal of custom stati in the post submit UI and a backend that makes those selections a reality.

#14122 would be easier to address if I knew whether my $status_obj->moderation property and status caps approach will fly.

I can explain the reasons for each change file by file, or further describe motivations and use cases. Would either of those be helpful?

@kevinB5 years ago

plugin to demonstrate custom stati "Approved" and "Secret". Corresponding roles of "Reviewer" and "Super Editor". v 1.1 adds registration of custom public status "Alternate" for post type and custom private status "Confidential" for page type.

comment:32 @kevinB5 years ago

Just updated the patch and demo plugin to:

  • support type-specific status registration
  • fully support custom public stati in the post edit UI, Edit Posts listing and everywhere else
  • support scheduled publishing to any public or private status. Previously, selection of private visibility forced post to be published immediately despite selection (and storage) of future date

Type-specific stati (governed by $status_obj->object_type array) can be registered in two ways:

  • register_post_status now supports object_type in $args array; registers the status to all object types by default
  • register_status_for_object_type( $post_status, $object_type ) - Add an already registered post status to an object type

Enforcement is via

// $post_type may be an individual value or an array
$private_stati = get_post_stati( array( 'object_type' => $post_type, 'private' => true ) );

To make that work, I had to modify function wp_list_filter to support the array value intersection:

function wp_list_filter( $list, $args = array(), $operator = 'and' ) {
	if ( empty( $args ) )
		return $list;

	$count = count( $args );

	$filtered = array();

	foreach ( $list as $key => $obj ) {
		$matched = array_intersect_assoc( (array) $obj, $args );

		foreach( array_keys( $matched ) as $_key ) {
			if ( is_array( $args[$_key] ) ) {
				if ( ! array_intersect( $args[$_key], $matched[$_key] ) )
					unset( $matched[$_key] );	
			}	
		}

		$num_matched = count( $matched );
		
		if ( ( 'and' == $operator && $num_matched == $count ) || ( 'or' == $operator && $num_matched ) ) {
			$filtered[$key] = $obj;
		}
	}

	return $filtered;
}

get_post_stati() and get_taxonomies() cast object_type argument to array to ensure the special treatment.

Please let me know what needs further explanation.

@kevinB5 years ago

comprehensive support for custom stati (public, private and moderation). RevC tightens code, fixes patch js bugs and a few core bugs (see comments). RevD registers and enforces type-specific stati, fleshes out custom public stati, allows scheduling to any public or private status. RevE is a 1-liner to include all readable stati in Recent Posts widget. RevF (15 Oct) fixes patch bugs related to sticky posts; supports custom public stati for sticky posts, term count, comment feed, archives, find posts, nav menu metabox & display

comment:33 @kevinB5 years ago

Updated patch fixes patch bugs related to sticky posts, defaults recent posts query to public stati only, and adds custom public stati support for:

  • sticky posts
  • term count
  • comment feed
  • archives
  • find posts
  • nav menu metaboxes and display

Also adds filters to support adjustment of those included stati:

  • 'posts_sticky_stati'
  • 'term_count_stati'
  • 'comment_feed_stati'
  • 'getarchives_stati'
  • 'find_posts_stati'
  • 'nav_menu_stati'

Also adds filters for default stati in the posts query (to support plugins dealing with content permissions):

  • 'posts_public_stati'
  • 'posts_private_stati'

comment:34 in reply to: ↑ description @markmcwilliams5 years ago

Replying to ptahdunbar:

Registering a post status via register_post_status() doesn't show the new status anywhere in the admin. [...] Post statuses should be registered to one or more post types.

Got a BIG +1 from me, interesting stuff happening though!

comment:35 @jane5 years ago

  • Keywords has-patch dev-feedback added; needs-patch removed

There are just a few days left before freeze, so asking committers to take a look and see if it can be finished off for 3.1 or not.

comment:36 @nacin5 years ago

  • Keywords dev-feedback removed
  • Milestone changed from 3.1 to Future Release
  • Type changed from task (blessed) to feature request

This is a huge undertaking, but I don't think we should rush this into 3.1. This looks like a great starting point. I'll support it as a task for 3.2 and I would be willing to work through it once we branch.

comment:37 @ninnypants5 years ago

  • Cc ninnypants added

comment:38 follow-up: @ryan_b4 years ago

One thing I should note, there should be an argument to hide a post status and an argument to limit what post types it can be used with, especially now that we have custom post types, maybe I want a status just for my custom post type. Or maybe I want a staus that can manually be selected it must be added by my plugin for whatever reason.

Just my 2 cents.

comment:39 @ucfknight104 years ago

what is the status of this ticket? as in, any idea when it will be completed and implemented? i'm writing a plugin for a client that allows the author of the post to set an expiration date, so i've created a post status called "expire" using register_post_status, and i would like to see this ticket implemented into wordpress soon. so, any news?

*withdrawn*

Last edited 4 years ago by ucfknight10 (previous) (diff)

comment:40 @BjornW4 years ago

  • Cc mailings@… added

comment:41 @danielbachhuber4 years ago

  • Cc danielbachhuber@… added

comment:42 @robmiller4 years ago

  • Cc r@… added

comment:43 @clemsos4 years ago

  • Cc clemsos added

comment:44 @Genesis20014 years ago

  • Cc zack@… added

comment:45 @bergius4 years ago

  • Cc bergius.tobias@… added

comment:46 @knutsp4 years ago

  • Cc knut@… added

comment:47 in reply to: ↑ 38 ; follow-up: @wlindley4 years ago

Replying to ryan_b:

...and an argument to limit what post types it can be used with, especially now that we have custom post types, maybe I want a status just for my custom post type...

Support. There needs to be an argument to register_post_status() whose value is an array of already-registered post_types to which the new post_status applies.

Alternately, register_post_type() could take an argument whose value is an array of already registered post_status values.

Furthermore, as of v3.1.3, the preamble to post.php contains eight calls to register_post_status, which are ignored by get_post_statuses() and get_page_statuses() -- which both are hard-coded, not to mention which line 109 says:

	register_post_status( 'pending', array(
		'label'       => _x( 'Pending', 'post' ),

while line 589 disagrees, returning the label:

		'pending'		=> __('Pending Review'),

Regardless, surely both get_post_statuses() and get_page_statuses() should simply return the data created by register_page_status() and register_post_type().

Last edited 4 years ago by wlindley (previous) (diff)

comment:48 in reply to: ↑ 47 @nacin4 years ago

Replying to wlindley:

Regardless, surely both get_post_statuses() and get_page_statuses() should simply return the data created by register_page_status() and register_post_type().

I believe those are just used for XML-RPC. The function to fetch statuses would be get_post_stati().

comment:49 @scribu4 years ago

Related: #17906

comment:50 @Horttcore4 years ago

  • Cc me@… added

comment:51 @danielbachhuber4 years ago

  • Cc d@… added

comment:52 @simonwheatley4 years ago

Related: #18578 (didn't spot this when I submitted mine)

comment:53 @simonwheatley4 years ago

  • Cc simon@… added

comment:54 @gcorne4 years ago

  • Cc gcorne@… added

comment:55 @lightningspirit4 years ago

  • Cc lightningspirit@… added

comment:56 @sidewindernet4 years ago

  • Cc sidewindernet added

comment:57 @alexkingorg4 years ago

  • Cc alexkingorg@… added

comment:58 @kevinB4 years ago

The patch functionality (custom privacy and moderation statuses) is now implemented via plugin.

comment:59 @lightningspirit4 years ago

How is the status os this patch? Will this be implemented in 3.4? Do you need any help testing and implementing it? I can help with anything implementing this API, but I don't know where to start it.
Can you please nacin or anyone else give me some directions?
Thanks

comment:60 @batmoo4 years ago

  • Cc batmoo@… added

comment:61 @flexicon4 years ago

  • Cc flexicon added

comment:62 @westi4 years ago

  • Keywords westi-likes 3.4-early added

This has a lot of discussion and patch work that we should consider what we want to do API wise to improve post_status support in core and what we don't want to support.

comment:63 @sirzooro4 years ago

  • Cc sirzooro added

comment:64 @sirzooro4 years ago

Please also add new function post_status_exists( $post_status ) - sometimes it may be handy to check if particular post status is registered. You can also add 2nd param $post_type, to check if post status exists for given post type (optional param, defaults to all post types).

comment:65 @markoheijnen3 years ago

  • Cc marko@… added

comment:66 @markoheijnen3 years ago

When this will be implemented this should also be implemented in xml-rpc. At this moment it is hardcoded.

comment:67 @stephenh19883 years ago

  • Cc stephenh1988 added

comment:68 @mattii3 years ago

  • Cc mattii added

comment:69 @scribu3 years ago

  • Keywords needs-refresh added

This needs a dedicated sub-team, if it's ever going to get off the ground.

comment:70 @danielbachhuber3 years ago

I'm happy to help on a subteam... I've done a lot of work with custom statuses and have a good understanding of where the weaknesses are.

comment:71 @scribu3 years ago

  • Keywords 3.4-early removed

I'm also willing to help, but it's too late for this in 3.4 (we're theoretically past freeze: http://wpdevel.wordpress.com/version-3-4-project-schedule/).

comment:72 @bergius3 years ago

  • Cc bergius.tobias@… removed

comment:73 @DrewAPicture3 years ago

  • Cc xoodrew@… added

comment:74 @lightningspirit3 years ago

Hi to all,
I really would like to help this topic and be also part of this subteam.
I think we need this feature in WordPress. I made some developments about this stuff in my instalations and I have some custom post types using this "meta" feature. I would like to contribute with them.
How can we join efforts to proceed with this?

comment:75 @philipjohn3 years ago

  • Cc philipjohn added

I brushed up the Codex article on this today and subsequently found this ticket. Adding myself to updates.

comment:76 @scribu3 years ago

Related: #20188

comment:77 @bergius3 years ago

Why is this ticket keep sending me notices when I've removed myself from the cc list?

comment:78 @scribu3 years ago

Because trac starts sending you notices the minute you do anything on a ticket: add a tag, add yourself to cc.

Please open a new ticket with the WordPress.org component to discuss this further.

comment:79 @benbalter3 years ago

  • Cc Ben@… added

@benbalter3 years ago

Updated patch to run with trunk, few bug fixes here and there

comment:80 @benbalter3 years ago

  • Keywords needs-testing added; needs-refresh removed

Uploaded attachment:12706.diff which ports the existing patch forward to work with trunk (r20434).

Also fixed a few bugs, and in the process, created a new get_object_stati() function (mirrored off of get_object_taxonomies()) to deal with wp_list_filter not liking nested arrays (specifically the object_type arg).

Still testing, and I'm sure there's stuff I missed, but worksforme.

Last edited 3 years ago by benbalter (previous) (diff)

comment:81 follow-up: @kevinB3 years ago

Although custom moderation and private stati are clearly useful and mesh well with the existing post_status implementation, custom public stati seem questionable. Can anyone think of a scenario in which they would be beneficial? All that comes to mind is:

  1. a single-term pseudo-taxonomy (probably unnecessary)
  2. allowing for distinctions in editing access without altering read access (potentially useful but arguably cludgy)

I'm not arguing for or against; just think it should be discussed before any code commits.

Another suggested topic for conversation: capability definitions and requirements related to custom stati. Any solution needs to regulate read, edit, delete and set (i.e. publish) of each custom post status, for each post type. The current patch does address these (just inviting further ideas).

comment:82 in reply to: ↑ 81 ; follow-up: @benbalter3 years ago

Replying to kevinB:

Although custom moderation and private stati are clearly useful and mesh well with the existing post_status implementation, custom public stati seem questionable. Can anyone think of a scenario in which they would be beneficial?

Anything that's not a blog post; that you don't "publish." If the final step of my workflow is "submitted" (think malange with applications) or "final" (think alfresco with press releases). If I'm a news organization and want to have a "breaking" post status at an intermediate step in my editorial process to display a teaser on the front-end. If I'm a car dealership (think autorader) and use my cars custom post type as either "available" (listed) or "sold" (not listed). If I have a coupon site (think retailmenot) in which everything is either valid or expired. Anytime a post isn't a blog post. (not to mention it's kinda silly to abstract 2/3s and hard code 1/3 which makes building queries, etc. a bit less intuitive).

comment:83 in reply to: ↑ 82 @kevinB3 years ago

Replying to benbalter:

Anything that's not a blog post; that you don't "publish."

I don't follow the correlation between being a blog post and having 'publish' status. Pages and other custom types have post_status = 'publish' too.

My working concept of the three post_status types:

  1. $status_obj->public : published to everyone
  2. $status_obj->private : published to those with sufficient capabilities
  3. $status_obj->moderation : not published at all, and editable based on capabilities

Maybe you would rather rename (3) to "workflow" or something else, but I don't see "something you don't publish" as a public status.

If the final step of my workflow is "submitted" (think malange with applications) or "final" (think alfresco with press releases).

"Submitted" is a moderation status in my book (not yet public).

"Final" would mean public but no longer editable by anyone, right? If so, that says my scenario (2) is real world and there are usages where a sequential post_status workflow that retains visibility but changes editability is not a cludge. Glad to hear it.

If I'm a news organization and want to have a "breaking" post status at an intermediate step in my editorial process to display a teaser on the front-end.

That's a compelling feature, but how would you retain that "breaking" flag and track progress through various steps of moderation, all with a single post_status field? Or do you have some other schema in mind to implement these stati?

If I'm a car dealership (think autorader) and use my cars custom post type as either "available" (listed) or "sold" (not listed).

If you want it for display customization, that sounds like a good job for a custom taxonomy. If for suppression (non-publishing), it sounds like a workflow status, not a public status.

If I have a coupon site (think retailmenot) in which everything is either valid or expired.

Same as above.

(not to mention it's kinda silly to abstract 2/3s and hard code 1/3 which makes building queries, etc. a bit less intuitive).

Yeah, I already wrote the code to implement custom public stati. Just wanted some confirmation that it's worthwhile and optimal.

comment:84 follow-up: @sirzooro3 years ago

@kevinB: in fact post statuses are a special kind of taxonomy, dedicated to manage "post" workflow. In addition they have extra support for visibility in core - depending on status post may or may not be displayed on front side. In general that extra support in core should let you decide what is better: custom post status(es) or custom taxonomy.

Few extra examples:

  • product page: draft, published, not available (temporarily), production stopped (page not visible);
  • ticket workflow: new, assigned, resolved, verified, closed, rejected;
  • movie page (for cinema): draft, screening/preview (there may be few of these), released, end of the screening;

comment:85 @alexkingorg3 years ago

I see status as internal workflow data. If you want to store data for decorating posts, that's where you want to use post meta. If you want to store data to use to query for specific posts, that would be a good place to use a custom taxonomy.

comment:86 in reply to: ↑ 84 @kevinB3 years ago

Currently, post_status is used to track workflow until publication. Then, upon publication it is primarily a visibility control (with corresponding editability control).

The current patch would expand that model as follows:

  1. additional moderation/workflow stages prior to publication (with corresponding set/edit/delete caps)
  2. additional visibility (privacy) statuses
  3. additional public statuses, which could be used to indicate further post-publication workflow (with possible distinctions in editing access)

The problem I see with (3) is that it could quickly overtax the one-status-per-post schema. What if you have already used a custom privacy status to customize visibility, but now want to make the post "final"? It seems that further post-publication editing access would be better handled via a separate status field that is dedicated to editability. If that is better left to a plugin, no problem ;)

Replying to sirzooro:

@kevinB: in fact post statuses are a special kind of taxonomy, dedicated to manage "post" workflow. In addition they have extra support for visibility in core...

Last edited 3 years ago by kevinB (previous) (diff)

comment:87 @bainternet3 years ago

  • Cc admin@… added

comment:88 @johnbillion3 years ago

  • Cc johnbillion@… removed

@benbalter3 years ago

Updated patch with bugfixes, refinements, and lastest trunk

comment:89 @benbalter3 years ago

Hoping to keep the ticket alive and kicking as planning gets under way for 3.5... updated the patch (attachment:12706-1.diff) with bug fixes and refinements and moved to latest trunk.

Although a bit rough around the edges, it appears to be somewhat stable for day-to-day use (I run it on a development box), and hooking into the API described above is fairly straightforward.

Outstanding: Potential tweaks to the publish metabox and quick edit

comment:90 @bradt3 years ago

  • Cc brad@… added

comment:91 @Viper007Bond3 years ago

  • Cc Viper007Bond added

Was disappointed to find that you can't register a custom post type to just a specific post_type like you can with a custom taxonomy and finally found this ticket. Would be great to get this into core.

comment:92 @wpsmith3 years ago

  • Cc travis@… added

comment:93 @navjotjsingh3 years ago

  • Cc navjotjsingh@… added

comment:94 @kovshenin3 years ago

  • Cc kovshenin@… added

comment:95 @jeherve3 years ago

  • Cc jeremy+wp@… added

comment:96 @jkudish3 years ago

  • Cc joachim.kudish@… added

comment:97 @tomauger3 years ago

  • Cc tomaugerdotcom@… added

comment:98 @williamsba13 years ago

  • Cc brad@… added

Is there any movement on this for 3.5? I'd love to see this get in this version!

comment:99 @markoheijnen3 years ago

For this getting in 3.5 it needs a lot of unit tests since the code will be changed a lot.

Looking trough the code I was wondering how the default statuses will get registered to the default post types. I'm probably missing something. Also doesn't it make more sense to create a WP_Post_Status class instead of using a global for that?

comment:100 @faulty3 years ago

  • Cc faulty added

comment:101 @helenyhou3 years ago

  • Keywords needs-refresh needs-unit-tests added

comment:102 @WraithKenny3 years ago

  • Cc Ken@… added

comment:103 @ryanduff3 years ago

  • Cc ryan@… added

comment:104 @JustinSainton3 years ago

  • Cc justinsainton@… added

This would be super slick. With as much traction as this has, and considering this is between hard and soft freeze - I'm curious as to whether or not this is too ambitious to consider this cycle, or if it's something we can mark as 3.6-early?

Personally, I'd be happy to contribute and invest some time for this cycle.

comment:105 @scribu3 years ago

If you want to make this get into Core faster, write some unit tests:

http://make.wordpress.org/core/handbook/automated-testing/

Unlike normal patches, unit test patches tend to get commited faster and don't get stale as fast.

comment:106 @helenyhou3 years ago

Also, as is noted, it needs a refresh. Been keeping an eye on this in relation to some parts of #21391.

comment:107 @JustinSainton3 years ago

Good points. @ryanduff and I will take some time in the next week or so to refresh and start some unit tests.

comment:108 follow-up: @nacin3 years ago

While important, I don't think it's only a matter of only a refresh and unit tests.

I've chatted with benbalter about this a few times. He studied the original patch for easily 10+ hours while updating it to trunk, so he's quite familiar. But he also didn't make any changes to it, instead simply refreshing a two-year-old patch based on a two-year-old API proposal.

I think, and he agrees, that the API as proposed is lacking, confusing, and needs some work.

My initial thoughts on reviewing it are:

  • The JS has a lot of room for improvement. Part of that is due to the age of the JS for the existing publish meta box.
  • The meta box code has a lot of room for improvement. Rather than being a somewhat elegant status API, it looks like a complete hack. Again, a lot of that is due to the existing code.
  • The "moderation" property is confusing and ill-defined.
  • Seems like we need a new query var. We currently have post_status = 'any' (along with post_type=any) as a "meta" status that maps to everything. This whole thing seems like a ripe situation to take the post_status and perm query variables and make them better.
  • That capabilities.php is untouched in the latest patch is incredibly odd, to say the least. map_meta_cap() supports custom post types and needs to support custom statuses for both built-in and custom post types.
  • When it comes to capabilities.php and query.php, the left hand doesn't talk to the right hand. The previous two bullet points outline the two different systems, which really shouldn't be two completely separate systems.
  • I randomly noticed that wp_count_posts() goes from 'draft, publish, future, pending, private' to only public statuses. There are many instances of raw SQL queries being changed — we need to thoroughly review these and ideally avoid direct SQL as much as possible.
  • The concept of a "scheduled status" (a post having a status outside of the fact that it is in the "future") is nice. Perhaps this should be spun off and implemented separately from custom post statuses. There's just too much going on here, and that seems like a good thing to start with. There are likely other things that could be done or spun off. For example, why must a "published" post have a date in the past? (Think an event in the future.) I'm not even sure if the API as designed handles that.

Overall, there's just so much to consider here, there's really no way it is happening for 3.5.

comment:109 in reply to: ↑ 108 @kevinB3 years ago

Replying to nacin:

  • That capabilities.php is untouched in the latest patch is incredibly odd, to say the least. map_meta_cap() supports custom post types and needs to support custom statuses for both built-in and custom post types.

The lack of change to function map_meta_cap() is explained by the patch's plugin roots. It can be filtered to apply additional capability requirements based on $post->post_status (as demonstrated in the old status-helper.zip). Maybe inelegant, but not that odd.

  • The "moderation" property is confusing and ill-defined.

Call it what you want, the idea is to allow for multiple statuses between draft and published, rather than hard-coding 'pending'. Each of those "moderation" statuses should have its own capability analogous to "publish_posts", as well as edit and delete caps. API should also allow control of which status (i.e. "Reviewed", "Approved" or "Dissed") is set by the "Publish" button when the user cannot publish.

comment:110 @dagtuts3 years ago

  • Cc dagtuts added

comment:111 @dspilka3 years ago

  • Cc dspilka added

comment:112 @mordauk3 years ago

  • Cc pippin@… added

comment:113 @F J Kaiser3 years ago

  • Cc 24-7@… added

comment:114 @travel-junkie3 years ago

  • Cc travel-junkie added

comment:115 follow-up: @BjornW3 years ago

Maybe I've missed this so please excuse me if this point has already been made (feel free to point me towards it).

I'm wondering if the current discussion on custom stati includes the possibility of having a published post/page workflow which has a new version currently in progress without taking the current version offline? Basically the ability to work on new drafts without having to take the current version offline akin to how autosave currently works.

A possible example use case could be:

Ann is an author who blogs about legislation. She wrote a post on law X some time ago. This law X is in the process of being be changed. She would like to update her old post on this law X, but keep the current version still online until the changes in law X have been agreed upon. In the meantime however she would like to update her old post, save the changes, but not make these changes public nor take the old post offline. She continues to work on her changes saving them, occasionally she invites a peer to have a look at her work and all this time the old post stays the same & online. After the changes in law X have been agreed upon she makes her changes public and this updates her old post online.

As far as I know WordPress does not support this use-case currently and it would be very nice if the new custom stati API would support these type of usecases where the publicize workflow of WordPress could be enhanced.

Btw the use-case described above is derived from both corporate & government clients who have a need for a more moderated publicize workflow due to the nature of their content, which for instance may be used in legislation.

If there is anything we can do to speed up the inclusion of this in the stati API, feel free to contact me.


comment:116 in reply to: ↑ 115 ; follow-up: @sbressler3 years ago

Replying to BjornW:

I'm wondering if the current discussion on custom stati includes the possibility of having a published post/page workflow which has a new version currently in progress without taking the current version offline? Basically the ability to work on new drafts without having to take the current version offline akin to how autosave currently works.

Not that this necessarily solves your entire use case, but Revisionary already handles a lot of what you're asking for.

comment:117 in reply to: ↑ 116 @BjornW3 years ago

Replying to sbressler:

Not that this necessarily solves your entire use case, but Revisionary already handles a lot of what you're asking for.

Thanks we had a look at the code of Revisionary and frankly I found at very large (loads of code which seems to be part of somekind of homebrew framework) & at first glance messy. Although it does work as advertised :) I might use it as a reference for a smaller plugin.

comment:118 follow-up: @nacin3 years ago

Ben Balter (who has been active on this ticket) has been working with a few others on a Post Forking plugin. I'd start there! https://github.com/benbalter/post-forking

comment:119 in reply to: ↑ 118 @BjornW3 years ago

Replying to nacin:

Ben Balter (who has been active on this ticket) has been working with a few others on a Post Forking plugin. I'd start there! https://github.com/benbalter/post-forking

Nacin, the link is dead & I don't see any repo resembling 'post-forking'? Are you sure it's called like that?

comment:120 @BjornW3 years ago

The link is now alive: https://github.com/benbalter/post-forking
and more information can be read here: http://postforking.wordpress.com

Last edited 3 years ago by BjornW (previous) (diff)

comment:121 @adamsewell3 years ago

  • Cc adam@… added

comment:122 @aaroncampbell2 years ago

  • Cc aaroncampbell added

comment:123 @ramiy2 years ago

  • Cc r_a_m_i@… added

comment:124 @slobodanmanic2 years ago

  • Cc slobodanmanic added

comment:125 @kovshenin2 years ago

  • Keywords editorial-flow added
  • Milestone changed from Future Release to 3.6

comment:126 in reply to: ↑ description @maxmaeteling2 years ago

  • Cc maxmaeteling added
Last edited 2 years ago by maxmaeteling (previous) (diff)

comment:127 @sabreuse2 years ago

  • Cc sabreuse added

comment:128 @goto102 years ago

  • Cc dromsey@… added

comment:129 @nacin2 years ago

  • Description modified (diff)
  • Type changed from feature request to task (blessed)
  • Version set to 3.0
Note: See TracTickets for help on using tickets.