WordPress.org

Make WordPress Core

Opened 5 years ago

Closed 6 weeks ago

Last modified 6 weeks ago

#18375 closed enhancement (fixed)

Post type templates

Reported by: johnbillion Owned by: swissspidy
Milestone: 4.7 Priority: normal
Severity: normal Version:
Component: Posts, Post Types Keywords: needs-dev-note
Focuses: template Cc:

Description

I'm increasingly finding situations where it would be nice to have the page template functionality available to custom post types (or, more specifically, available to all post types instead of just pages).

From a technical point of view there aren't many changes needed in core to support templates for all post types, but there may be some things to consider regarding the best way to go about it.

Patch coming up for my first pass at it.

Related:

Note that the Custom Post Template plugin has 37k downloads so the demand is there.

Attachments (10)

18375.patch (8.4 KB) - added by johnbillion 5 years ago.
18375.2.patch (11.5 KB) - added by Mte90 4 months ago.
new refreshed working version
18375.diff (24.7 KB) - added by swissspidy 3 months ago.
18375.2.diff (22.7 KB) - added by Mte90 2 months ago.
now use get_file_data
18375.3.diff (22.7 KB) - added by dipesh.kakadiya 7 weeks ago.
Updated metabox title with singular post type name
18375.4.diff (22.8 KB) - added by dipesh.kakadiya 7 weeks ago.
Used sprintf() and _x() ensures translators can provide better contextual translations.
18375.5.diff (29.4 KB) - added by swissspidy 7 weeks ago.
18375.6.diff (29.7 KB) - added by swissspidy 7 weeks ago.
18375.7.diff (29.7 KB) - added by swissspidy 7 weeks ago.
18375.8.diff (36.9 KB) - added by swissspidy 7 weeks ago.
Improve attachment support and body class handling

Download all attachments as: .zip

Change History (68)

#1 @johnbillion
5 years ago

  • Keywords has-patch added

Patch that adds per-post-type template functionality to all post types.

A template in a theme can now include an optional 'Template Type' header that specifies the post type that the template is for. If the header isn't present, the template is treated as a page template.

Example:

/*
 * Template Name: Amazing Event
 * Template Type: event
 */

This header placed in a template file will make the Amazing Event template available to the event post type, meaning it can be selected in the Template dropdown on the post editing screen.

#2 @johnbillion
5 years ago

Whoops, messed the first patch up. Updated.

A template can also specify multiple post types it can be used for:

/*
 * Template Name: Amazing Template
 * Template Type: post, page, event
 */

The 'Amazing Template' would be available to select for all posts, pages and events.

@johnbillion
5 years ago

#3 @johnbillion
5 years ago

Third time lucky. Serves me right for running multiple patches on the same install.

#4 follow-up: @scribu
5 years ago

I'm not sure this is worth doing without #11216

#5 follow-up: @andrewryno
5 years ago

Other than having a UI to do it, what's the benefit above just using archive-{post_type}.php, single-{post_type}.php, etc. If you do this for post types, would it only apply that template for the single post page?

I could see it being nice for individual posts or something, but if you are just going to apply it across all the posts within that type, what's the point? I'm probably just missing a proper use case for it, though.

#6 follow-up: @scribu
5 years ago

Yes, these templates would only be used for individual posts.

However, I'm also having difficulty figuring out a use-case for it.

Last edited 5 years ago by scribu (previous) (diff)

#7 in reply to: ↑ 4 @johnbillion
5 years ago

Replying to scribu:

I'm not sure this is worth doing without #11216

Yep, I agree.

#8 in reply to: ↑ 6 @johnbillion
5 years ago

Replying to scribu:

Yes, these templates would only be used for individual posts.

However, I'm also having difficulty figuring out a use-case for it.

The use-case is exactly the same as the use-case for page templates. It allows users to select different templates on a per-post basis.

#9 in reply to: ↑ 5 @johnbillion
5 years ago

Replying to andrewryno:

I could see it being nice for individual posts or something, but if you are just going to apply it across all the posts within that type, what's the point? I'm probably just missing a proper use case for it, though.

I think you're misunderstanding slightly. All this is doing is applying the page templates functionality (ie. the dropdown menu that allows users to select from several available custom page templates) to all post types instead of just pages.

#10 @sc0ttkclark
4 years ago

  • Cc lol@… added

What about doing this as a 'supports' option for post types? 'supports' => array( 'title', 'editor', 'page-attributes', 'page-template' )

One caveat would be that it would require page-attributes to be shown.

Never-the-less, I'd like to be able to use Page Templates for Custom Post Types, I'm not sure post-type specific page templates would be better.

#11 @amtiskaw
4 years ago

  • Cc amtiskaw added

I have a requirement on my current project to let users choose between a regular and full-width template for a custom post type. No problem, I thought, But then I discovered template selection is only possible for regular posts, and not for custom post types.

I figured there must be some difficult obstacle to implementing this, but now I see that someone has already implemented it, over a year and half ago, but nobody has bothered to land the patch? What exactly is the hold-up here? All I see in this thread is quibbling by people who don't even seem to understand what page templates are for.

#12 @SergeyBiryukov
4 years ago

#24400 was marked as a duplicate.

#13 @nacin
3 years ago

  • Component changed from Themes to Posts, Post Types
  • Focuses template added

#14 @chrisvanpatten
3 years ago

Just to offer potential use-cases, I'm working on a project that needs the ability to make "longreads" posts look different (sort of in the "art-directed" style of The Verge/Polygon/et al), and we're creating a few different templates so the editors can choose different styles for each of those articles. Post/Page Templates are perfect for that.

I also have another client looking to have certain posts show author boxes and avatars, among other small changes (these are posts from "guest contributors" vs. posts from regular writers). There are plenty of ways to handle that, but Post Templates seem like a natural fit that's easy for the client to use.

I'm using the Post Template plugin that @johnbillion linked to above, but having it in core would be even better :)

#15 @SergeyBiryukov
3 years ago

#27500 was marked as a duplicate.

#17 @lgladdy
3 years ago

We're building a massive site for a major public sector organisation who want to be able to create pages, but in order to separate the core "corporate" pages with other pages, we wanted to create CPTs to handle that segmentation, but they need to support templating for us to do that.

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

#18 @stewarty
20 months ago

Just to add a new use case here.

Currently building a project involving landing pages.

Landing pages are setup as a custom post type but we need multiple templates. (Three different templates)

We've engineered around the problem now, the odd thing is that it seems WordPress goes out of it way to stop you implementing this at every stage. Full of post_type == 'page' conditionals that you can't really avoid so you end up recreating a lot of core code in a plugin.

Would be nice to see this officially supported.

#19 @jhned
19 months ago

Just to add another use case-- we recently wanted to add a new format to our custom post type "Projects" for case studies. Since the case studies format has completely different markup, content and styles, I needed to set it up as a page template, and used a plugin that extended the functionality to the custom post type.

#20 @Mckilem
10 months ago

Given the increased demands by clients for post templates (we do have some options, such as few outdated plugins and plugins such as display widgets to control which widget shows on which post), but all of that would not be necessary if there would be an option to use templates not only on pages, but on posts and all other custom post types.

What are the current considerations on whether we can expect this in future releases?

#21 @mor10
9 months ago

For years I've been asking
why Pages were unique,
why Custom and Template are words reserved
for content belonging to the singular, static clique.

What is a Page but an island?
Unconnected, alone, a windswept highland
bereft the bridges that tie it to others
its only relations the family it fosters.

Is this why Template Name is reserved for Pages?
A feeble gesture to make them feel they don't live in cages?

Or is it something deeper?
A notion that Posts must be kept in line,
that uniqueness in ephemera
is the aftermath of leaded wine.

What world would we live in
if Posts showed their true nature?
How wild and chaotic
how unfitting our beloved nomenclature.

"Cast freedom to the wayside" they say:
"If Posts want character,
let them try:
Fit the Post Formats preordained,
conform,
or scrape by," on a wing and a prayer
that a non-standard solution
is better than codified absolution.

To this I have but one thing to say:
Posts are unique, so let them have their way.
Templates are what we build,
for posts,
for pages,
it's the nature of our Guild.

Let's end this segregation,
this illusion that only Pages are unique.
All post types deserve templates!
It's such a small, harmless tweak.

This ticket was mentioned in Slack in #core by sc0ttkclark. View the logs.


9 months ago

#23 @ericlewis
9 months ago

  • Keywords dev-feedback removed

A bunch of people have provided use cases for this, and this seems like a sensical enhancement. Adding to future release.

The patch is rather old, will need a refresh as well as account for the last five years.

#24 @ericlewis
9 months ago

  • Keywords needs-refresh added; has-patch removed
  • Milestone changed from Awaiting Review to Future Release

#25 @jorbin
4 months ago

  • Keywords needs-unit-tests added

This would be nice to get into 4.7. To do so, it's going to require a refresh of the patch and some unit tests.

@Mte90
4 months ago

new refreshed working version

#26 @Mte90
4 months ago

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

That patch contains respect the old one:

  • The check to include the Attributs metabox in admin it's moved inside the metabox to show the Template in all the post types and Order and Parent are showed only on Page post type
  • The page_templates key for cache changed on post_templates
  • Added theme_page_templates filter

Respect to the old:

  • Updated the code in few part of the code itself
  • Use the new WP internal for get the header information about the page name

#27 @swissspidy
3 months ago

  • Keywords dev-feedback removed

Thanks for the patch @Mte90! I'll look into it and try to provide some tests.

@swissspidy
3 months ago

#28 @swissspidy
3 months ago

  • Keywords has-unit-tests added; needs-unit-tests removed
  • Milestone changed from Future Release to 4.7

In 18375.diff:

  • Do not introduce new functions everywhere, at least for now.
  • Remove checks for the 'post' post type in various places (get_page_template_slug(), WP_Posts_List_Table (quick edit), is_page_template(), wp_insert_post() etc.)
  • Also makes this work in the WP_Post class
  • Adds a new attributes post type label as it now affects much more post types
  • Adds unit tests or modifies existing ones where necessary.

Basically, this adds support for custom templates for any post type that supports page-attributes. That means with the current patch it doesn't work for posts by default.

To do:

  • Discuss backward compatibility:
    • Should the 'page_templates' cache group change to 'post_templates' or should there be both? If it should change, the docs inside WP_Theme need to reflect that.
    • Add new params or new is_post_type_template() / get_post_type_templates() functions? It's totally confusing when there's get_page_templates() and get_page_template()
    • Should the 'post' post type have the page-attributes support by default?
  • Test all the things: custom post types, posts, pages, quick edit, etc.

Feedback welcome.

#29 @Mte90
3 months ago

Well the new code is amazing :-D

Should the 'page_templates' cache group change to 'post_templates' or should there be both? If it should change, the docs inside WP_Theme need to reflect that.

As I can see in the code the only reference for that value is inside WP_Theme so maybe it's better to check if there are plugins that use that value.

Add new params or new is_post_type_template() / get_post_type_templates() functions? It's totally confusing when there's get_page_templates() and get_page_template()

I think to maintain the old for compatibility and new one to use the new functions and to avoid confusions.

Should the 'post' post type have the page-attributes support by default?

I don't think probably there are not many website that will use this feature so enable mandatory is not the best way. And also only the people that know that feature will use it.

#30 @swissspidy
3 months ago

I'll try to update the patch over the next day.

I think we should use get_file_data() for retrieving the headers as it's more reliable and reduces the risk of getting false positives. The current regex is over the whole PHP file.

#31 follow-up: @WPDevHQ
2 months ago

How are we adding this to themes - via

add_theme_support()

or a filter via a function callback?

#32 in reply to: ↑ 31 ; follow-up: @Mte90
2 months ago

Replying to WPDevHQ:

How are we adding this to themes - via

add_theme_support()

or a filter via a function callback?

Edit: my fault the right code to use it:

function wpcodex_add_page_attributes_support_for_posts() {
	add_post_type_support( 'post', 'page-attributes' );
}
add_action( 'init', 'wpcodex_add_page_attributes_support_for_posts' );

That generate an error on that patch: Notice: Undefined property: stdClass::$attributes in /srv/www/wordpress-develop/src/wp-admin/edit-form-advanced.php on line 263

Last edited 2 months ago by Mte90 (previous) (diff)

#33 in reply to: ↑ 32 @WPDevHQ
2 months ago

Replying to Mte90:

Edit: my fault the right code to use it:

function wpcodex_add_page_attributes_support_for_posts() {
	add_post_type_support( 'post', 'page-attributes' );
}
add_action( 'init', 'wpcodex_add_page_attributes_support_for_posts' );

Thanks for that - I was hooking to after_setup_theme and it didnt fire

That generate an error on that patch: Notice: Undefined property: stdClass::$attributes in /srv/www/wordpress-develop/src/wp-admin/edit-form-advanced.php on line 263

@Mte90
2 months ago

now use get_file_data

#34 follow-up: @Mte90
2 months ago

The difference respect 18375.diff:

#35 in reply to: ↑ 34 ; follow-up: @WPDevHQ
2 months ago

Replying to Mte90:

The difference respect 18375.diff:

In the diff there seems to be a revertion for wp-admin/edit-form-advanced.php

+if ( post_type_supports( $post_type, 'page-attributes' ) ) {
+	add_meta_box( 'pageparentdiv', 'page' == $post_type ? __('Page Attributes') : __('Attributes'), 'page_attributes_meta_box', null, 'side', 'core' );
+}

Shouldn't that be

+if ( post_type_supports( $post_type, 'page-attributes' ) ) {
+	add_meta_box( 'pageparentdiv', $post_type_object->labels->attributes, 'page_attributes_meta_box', null, 'side', 'core' );
+}

Not checked further

#36 @WPDevHQ
2 months ago

I've applied the patch from 18375.2.diff above and I can only get the Attributes meta box to show but no templates :-$

#37 in reply to: ↑ 35 @Mte90
2 months ago

Replying to WPDevHQ:

Replying to Mte90:

The difference respect 18375.diff:

Here I explained why the problem happen and why of this choose, and for the template you have to add that in a your template file https://core.trac.wordpress.org/ticket/18375?replyto=35#comment:1

#38 @swissspidy
2 months ago

  • Owner set to swissspidy
  • Status changed from new to assigned

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.


2 months ago

#40 @swissspidy
2 months ago

Not use the labels->attributes but use the old code to print Page Attributes/Attributes as explained on https://core.trac.wordpress.org/ticket/18375#comment:32

Using post type labels is really the way to go here. Looking at the latest patch now.

This ticket was mentioned in Slack in #core by desrosj. View the logs.


8 weeks ago

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.


7 weeks ago

@dipesh.kakadiya
7 weeks ago

Updated metabox title with singular post type name

#43 @dipesh.kakadiya
7 weeks ago

@swissspidy

Updated 'pageparentdiv' metabox title as below.

Replaced

'page' == $post_type ? __('Page Attributes') : __('Attributes')

with

esc_html( $post_type_object->labels->singular_name . __('Attributes') )

#44 @sc0ttkclark
7 weeks ago

@dipesh.kakadiya you should be using esc_html( sprintf( _x( '%s Attributes', 'Singular page attributes meta box title' ), $post_type_object->labels->singular_name ) ) and perhaps split that up across a few lines to keep things clean.

Using sprintf() and _x() ensures translators can provide better contextual translations.

@dipesh.kakadiya
7 weeks ago

Used sprintf() and _x() ensures translators can provide better contextual translations.

#45 @dipesh.kakadiya
7 weeks ago

@sc0ttkclark

Thanks for suggestion, Patch refreshed with that

@swissspidy
7 weeks ago

#46 follow-up: @swissspidy
7 weeks ago

@sc0ttkclark @dipesh.kakadiya Unfortunately this approach does not work. In many languages, translations are different depending on the post type. One can't pass variables as the context for translation functions. Thus, extending post type labels is the only viable approach.

I attached a new patch in 18375.5.diff. There were only some minor changes compared to the previous one. Now, a post type does not need to support page-attributes in order to be able to select a template. For example, if there's at least 1 template for the 'post' post type, the meta box will be displayed — without the page attributes stuff like order and hierarchy of course.

@johnbillion @DrewAPicture @ocean90 Does anyone want to give this a go? It would be great to get this in before beta 1.

#47 in reply to: ↑ 46 ; follow-up: @ocean90
7 weeks ago

I have no strong opinion on the feature per se, but I can give you some feedback on 18375.5.diff

#48 in reply to: ↑ 47 @Mte90
7 weeks ago

I am agree with this improvement but for:

Replying to ocean90:

  • Using theme_page_templates for all post types could be a back-compat issue. Maybe theme_page_templates should only be used for the post type page and a new one, theme_post_templates, for other post types.

Maybe to improve term consistency it's better theme_post_type_templates where theme_page_templates is a wrapper for that. In that way post type templates support all the post types. In many languages the term post is used to say post type but also a post as article so specify can improve the meaning for developers.

This ticket was mentioned in Slack in #core by jeffpaul. View the logs.


7 weeks ago

@swissspidy
7 weeks ago

#50 @swissspidy
7 weeks ago

In 18375.6.diff:

  • Do not use get_file_data() because of some failed tests
  • Change theme_page_templates to a dynamic theme_{$post_type}_templates hook
  • Change Template Type to Template Post Type

Travis CI build: https://travis-ci.org/aaronjorbin/develop.wordpress/builds/170398285

Oh, and I'll change the yoda conditions in a next patch.

@swissspidy
7 weeks ago

#51 @swissspidy
7 weeks ago

18375.7.diff fixes the yoda conditions.

#52 @swissspidy
7 weeks ago

  • Keywords needs-dev-note commit added

@swissspidy
7 weeks ago

Improve attachment support and body class handling

#53 @swissspidy
6 weeks ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 38951:

Posts, Post Types: Add support for post type templates.

WordPress has supported custom page templates for over 12 years, allowing developers to create various layouts for specific pages.
While this feature is very helpful, it has always been limited to the 'page' post type and not was not available to other post types.

By opening up the page template functionality to all post types, we continue to improve the template hierarchy's flexibility.

In addition to the Template Name file header, the post types supported by a template can be specified using Template Post Type: post, foo, bar.
When at least one template exists for a post type, the 'Post Attributes' meta box will be displayed in the back end, without the need to add post type support for 'page-attributes'. 'Post Attributes' can be customized per post type using the 'attributes' label when registering a post type.

Props johnbillion, Mte90, dipesh.kakadiya, swissspidy.
Fixes #18375.

#54 @johnbillion
6 weeks ago

  • Keywords has-patch has-unit-tests commit removed

This ticket was mentioned in Slack in #core by ocean90. View the logs.


6 weeks ago

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


6 weeks ago

#57 @NateWr
6 weeks ago

I had no idea this was in the works. Absolutely love it!

One minor hiccup: if a theme implements a custom post type template and a user is using the theme on a pre-4.7 version of WordPress, the template will show in the list of Page Templates.

Probably not that big of a deal, but in case anyone has good ideas for working around this I thought I'd bring it up.

#58 @swissspidy
6 weeks ago

@NateWr Good point. I'll include an example in the make/core post I'm currently writing.

Note: See TracTickets for help on using tickets.