Make WordPress Core

Opened 12 years ago

Last modified 4 months ago

#19958 accepted enhancement

Allow custom post types as "home" and get_posts() to return results for more than one post type

Reported by: sooskriszta's profile sooskriszta Owned by: pbearne's profile pbearne
Milestone: Future Release Priority: normal
Severity: normal Version: 3.3.1
Component: Posts, Post Types Keywords: needs-testing needs-design has-patch has-screenshots
Focuses: accessibility, administration Cc:

Description

In

Wordpress admin > Settings > Reading

there is an option to define what the home page or the front page should be

Front page displays

Radio button

A static page (select below)

is followed by a dropdown containing a list of all pages.

I would request that custom page types be allowed in this dropdown. This way, I could make my bbPress forums or my All-in-one event calendar, etc my homepage.

Attachments (5)

CustomPostTypeAsHomePages.patch (3.0 KB) - added by pbearne 11 years ago.
incomplete patch
CustomPostTypeAsHomePages.2.patch (4.5 KB) - added by pbearne 11 years ago.
incomplete patch after tonight work
CustomPostTypeAsHomePages.3.patch (8.1 KB) - added by pbearne 11 years ago.
Current dev version (not working)
CustomPostTypeAsHomePages.ui.refreeh.2.patch (11.7 KB) - added by pbearne 4 years ago.
remove the not needed file in patch
19958.png (77.6 KB) - added by afercia 4 years ago.

Download all attachments as: .zip

Change History (56)

#1 @pbearne
11 years ago

  • Cc pbearne@… added
  • Severity changed from normal to major
  • Type changed from enhancement to defect (bug)

This is needed or / and an option to push / block it in the custom post type config / setup

Last edited 11 years ago by pbearne (previous) (diff)

#2 @SergeyBiryukov
11 years ago

  • Type changed from defect (bug) to enhancement

Related: #16379

#3 @jpyper
11 years ago

  • Cc jarrod@… added

What about instead putting a filter on the arguments for the wp_dropdown_pages call that produces the list of pages to choose from (line 96 in wp-admin/options-reading.php)? A developer could then use :

function filter_my_cpt($args) {
  $args[post_type] = 'cpt-slug';[[BR]]

  //to also maintain pages: $args[post_type] = 'pages, cpt-slug'
}
add_filter('options-front-page' , filter_my_cpt');
add_filter('options-posts-page' , filter_my_cpt');
Last edited 10 years ago by SergeyBiryukov (previous) (diff)

#4 @pbearne
11 years ago

Yes feels that it would work

wp_dropdown_pages() call's get_pages() just passing the args through and get_pages() takes in post_type

And if we update the custom post/page type page to inform how to add this

I don't see the need to add it to the posts page as this is just a place holder so remove that from the code.

Added (untested) code to make the filter work with any number of filters so that this call can be part of custom post/page type page setups.

function filter_my_cpt($args) {
// pass through current value if any to allow for other filters
  if(count($args[post_type])>0){
     $args[post_type] = array_push($args[post_type],'cpt-slug');
  }else{
     $args[post_type] = 'cpt-slug';
  }

}
add_filter('options-front-page' , filter_my_cpt');

so the change to options-reading.php would just a filter around the front page $args array

I that feel we should break this out a bit to make readable but this looks like the code we need.

117<ul>
     <li><label for="page_on_front"><?php printf( __( 'Front page: %s' ), wp_dropdown_pages(apply_filters('options-front-page', array( 'name' => 'page_on_front', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_on_front' ) ) ) ) ); ?></label></li>
     <li><label for="page_for_posts"><?php printf( __( 'Posts page: %s' ), wp_dropdown_pages( array( 'name' => 'page_for_posts', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_for_posts' ) ) ) ); ?></label></li>
</ul>

Does this all make sense?

Paul

#5 @jpyper
11 years ago

Yes, that's a better idea for a function to utilize the filter and makes sense to me.

#6 @jpyper
11 years ago

I was doing some testing and I think I see a further problem. WP doesn't seem to properly handle having a CPT as the front page in some aspects.

For instance, the url for the front page doesn't get changed to just website.com, it's website.com/post-type/post-slug. Same goes for when a link to the new "front page" is placed in a menu. Normally the link is changed to just be website.com but it keeps it's full URL.

Part of that problem seems to be in /wp-admin/includes/nav-menu.php about line 726. It checks for a post type name of 'page' before changing the url out for menus. I haven't found where it does the URL change for the URL of the front of the site.

#7 @pbearne
11 years ago

Pain

Lets keep digging

Paul

#8 @pbearne
11 years ago

We could just reverse this

	if ( 'page' == $post_type_name ) {

becomes

	if ( 'post' != $post_type_name ) {

and let the

if ( ! empty( $front_page ) ) {

do it's stuff for all the menu types but this would mean that the code will run more than needed

So the other way would to do a look-up for the page type that is used for the home page test for that setting 'page' as the default as we might not get anything back

$front_page_type = 'page' == get_option('show_on_front') ? 
                 get_post_type((int) get_option( 'page_on_front' )) : 'page';

if($front_page_type == $post_type_name ){
 ...

If this works it's better and cover all the bases

or this might be even better

$front_page_type = 'page' == get_option('show_on_front') ? 
                 get_post_type((int) get_option( 'page_on_front' )) : null;

if($front_page_type == $post_type_name ){
 ...

Paul

#9 @pbearne
11 years ago

Hi

I have done some work on this but have not sorted the URL code

So I am just pasting the patch for now

Index: wp-admin/options-reading.php
===================================================================
--- wp-admin/options-reading.php	(revision 22831)
+++ wp-admin/options-reading.php	(working copy)
@@ -114,7 +114,7 @@
 	</label>
 	</p>
 <ul>
-	<li><label for="page_on_front"><?php printf( __( 'Front page: %s' ), wp_dropdown_pages( array( 'name' => 'page_on_front', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_on_front' ) ) ) ); ?></label></li>
+	<li><label for="page_on_front"><?php printf( __( 'Front page: %s' ), wp_dropdown_pages( apply_filters('options-front-page',array( 'name' => 'page_on_front', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_on_front' ) ) ) ) ); ?></label></li>
 	<li><label for="page_for_posts"><?php printf( __( 'Posts page: %s' ), wp_dropdown_pages( array( 'name' => 'page_for_posts', 'echo' => 0, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => get_option( 'page_for_posts' ) ) ) ); ?></label></li>
 </ul>
 <?php if ( 'page' == get_option( 'show_on_front' ) && get_option( 'page_for_posts' ) == get_option( 'page_on_front' ) ) : ?>
Index: wp-includes/post.php
===================================================================
--- wp-includes/post.php	(revision 22831)
+++ wp-includes/post.php	(working copy)
@@ -3628,9 +3628,14 @@
 	$number = (int) $number;
 	$offset = (int) $offset;
 
-	// Make sure the post type is hierarchical
+	// Make sure we have a valid post type
+	if ( !is_array( $post_type ) )
+		$post_type = explode( ',', $post_type );
+	if ( array_diff( $post_type, get_post_types() ) )
+		return $pages;
+	// Make sure the all post types are hierarchical
 	$hierarchical_post_types = get_post_types( array( 'hierarchical' => true ) );
-	if ( !in_array( $post_type, $hierarchical_post_types ) )
+	if ( array_intersect( $post_type, $hierarchical_post_types ) == count($post_type) )
 		return $pages;
 
 	// Make sure we have a valid post status
@@ -3733,11 +3738,19 @@
 	if ( $parent >= 0 )
 		$where .= $wpdb->prepare(' AND post_parent = %d ', $parent);
 
+	// Check if post_type is an array so that Custom Page types can be added to dropdowns and lists
+	if ( 1 == count( $post_type ) ) {	
+		$where_post_type = $wpdb->prepare("post_type = %s"  , array_shift( $post_type ) );
+	} else{
+		$post_type = implode( "', '", $post_type );
+		$where_post_type = "post_type IN ('$post_type')";
+	}
+
 	if ( 1 == count( $post_status ) ) {
-		$where_post_type = $wpdb->prepare( "post_type = %s AND post_status = %s", $post_type, array_shift( $post_status ) );
+		$where_post_type .= $wpdb->prepare( " AND post_status = %s",  array_shift( $post_status ) );
 	} else {
 		$post_status = implode( "', '", $post_status );
-		$where_post_type = $wpdb->prepare( "post_type = %s AND post_status IN ('$post_status')", $post_type );
+		$where_post_type .= "AND post_status IN ('$post_status')" ;
 	}
 
 	$orderby_array = array();

the test functions I used where

add_action( 'init', 'create_post_type' );
function create_post_type() {
	register_post_type( 'acme_product',
		array(
			'labels' => array(
				'name' => __( 'tests' ),
				'singular_name' => __( 'test' )
			),
			'public' => true,
			'has_archive' => true,
			'rewrite' => array('slug' => 'tests'),
		)
	);
}


function filter_my_cpt($args) {
	$args['post_type'] = array('page', 'acme_product');
	return $args;
}

add_filter('options-front-page' , 'filter_my_cpt');

I will look at the URl code later

And I want to look getting this into the register_post_type() call

#10 @pbearne
11 years ago

I see the bug on the menus I will need to be look for if there is a set home page and then test for that post type add add the Home: XXXXX to the correct list

#11 follow-up: @SergeyBiryukov
11 years ago

You should attach the patch as a file instead of pasting it in the comment box.

#12 in reply to: ↑ 11 @pbearne
11 years ago

Replying to SergeyBiryukov:

You should attach the patch as a file instead of pasting it in the comment box.

even if its not complete?
I have more work to do before finished.

#13 @SergeyBiryukov
11 years ago

Yes, just leave a note about what's already implemented and what else needs to be done.

It's easier to follow the discussions and development when patches are in separate files.

@pbearne
11 years ago

incomplete patch

#14 @pbearne
11 years ago

Just added a patch this works OK but WP has "page" hard coded in a few places so I need to provide patch's so that we do a look-up for the page type for the home page see nav-menu.php line 729 and jpyper comment above for example.

We also need to find and recode the rewrite rule that hides the path/filename when loading a homepage

I also what to have look at what changes would be needed to make this a switch in the register_post_type function and not a extra filter step

And it would be good to check that we keep "page" in the $args!['post_type'!] array

#15 @pbearne
11 years ago

Notes to self

check that removing $wpdb->prepare have I broken SQL santation
this looks OK as we check for valid values before using them

check this 3639

 if ( array_intersect( $post_type, $hierarchical_post_types ) == count($post_type) ) 
               return $pages; 

this should be a not the same return need to check the output of array_intersect maybe use array_diff

Last edited 10 years ago by SergeyBiryukov (previous) (diff)

#16 @pbearne
11 years ago

  • Summary changed from Allow custom post types as "home" to Allow custom post types as "home" and get_posts() to return results for more than one post type

@pbearne
11 years ago

incomplete patch after tonight work

#17 @pbearne
11 years ago

  • Keywords has-patch needs-testing needs-codex added

This now all works

Apart from if a custom post type is set as a home page it does get servered as the root page eg. Domain.com rather at the URL of domain.com/customPostType/pagename the code for this looks like its somewhere in query.php so might be better if someone else who knows that code looks at that.

And I haven't add code to register_post_type make this a feature but will look at that this week

Last edited 11 years ago by pbearne (previous) (diff)

#18 @toscho
11 years ago

  • Cc info@… added

#19 @wpsmith
11 years ago

  • Cc travis@… added

#20 @SergeyBiryukov
11 years ago

#23100 was marked as a duplicate.

@pbearne
11 years ago

Current dev version (not working)

#21 @pbearne
11 years ago

Hi All

I need a bit of help to finish this

I have one last bug and need a code review as the function I added to options-reading needs to be move to better location.

The bug: WordPress doesn't render the custom page at the root all I am getting the 404 page

if you look at line 109 in query.php you will see I have remove the hardcoded "page" and pass in the current page type.

Without this change the custom page loads but with the URL of /pagetype/pagename and not at the root /

With this change I am getting the 404 so there is an additional change needed somewhere

I am sure that this will come back for some rework on variable name etc.

use this function to test, Note the 'show_in_home_page_list'=> true, which how I am declaring that this custom post should be added to the list

add_action( 'init', 'create_post_type' );
function create_post_type() {
	register_post_type( 'acme_product',
		array(
			'labels' => array(
				'name' => __( 'tests' ),
				'singular_name' => __( 'test' )
			),
			'public' => true,
			'has_archive' => true,
			'rewrite' => array('slug' => 'tests'),
			'hierarchical' => true,
			'show_in_home_page_list'=> true,
		)
	);
}

I have tried to remove all the hard code strings so in itself will an improvement.

All and any help to finish this gratefully accepted.

#22 @navjotjsingh
11 years ago

  • Cc navjotjsingh@… added

#23 @jeremyfelt
10 years ago

  • Component changed from Administration to Posts, Post Types
  • Focuses administration added
  • Severity changed from major to normal

#24 @SergeyBiryukov
10 years ago

#27685 was marked as a duplicate.

#25 @iammathews
9 years ago

What's the status on this?

#26 @chriscct7
8 years ago

  • Keywords needs-refresh added

#27 @swissspidy
8 years ago

I think this would be a very interesting enhancement and would make the front page setting much more flexible.

It should be possible to either set a specific post (no matter what post type, think public => true) or a post type archive (thinkhas_archive => true) as the front page. I don't think a new show_in_home_page_list argument is really needed. A filter should suffice.

Perhaps we need to look at the UI first? Related: #16379

#28 follow-up: @pbearne
8 years ago

I thought this was dead
Yes a filter would a way to go
just added them to a drop-down (maybe grouped) could cause it to get very long so a UI update would help

happy to refresh when needed

#29 in reply to: ↑ 28 @DrewAPicture
8 years ago

  • Keywords needs-codex removed

Replying to pbearne:

happy to refresh when needed

Happy to consider a refreshed patch :-)

#30 @pbearne
4 years ago

  • Keywords has-patch removed
  • Owner set to pbearne
  • Status changed from new to accepted
  • Version changed from 3.3.1 to trunk

This ticket got a short out in https://wptavern.com/wordpress-5-6-wish-list-homepage-post-type-selection-and-block-management so I am starting to work on it along with anybody who would like to help and let's see if we can this in 5.6

I have a patch with an updated UI for admin which I would like to get validated as the right direction

As came back to this after 8 years I made a few other changes

We control which post types are allowed to be used in homepage content via a new arg in register_post_type()

'show_in_home_page_list'=> true,

backed up by a filter post_types_allowed_on_home_page

$post_types_allowed_on_home_page = apply_filters( 'post_types_allowed_on_home_page', array_keys( get_post_types( array( 'show_in_home_page_list' => true ) ) ) );

If the post capability_type of "post" the I propose we allow it to be swapped for the post type "post" and render on the homepage

To support this we should a new template file front-page-{post-type}.php and then follow the custom post type root archive-{post_type}.php => home.php this would allow a theme to provide a different layout for content if render as home page

If a post type other than "post" is set we should allow setting a page to render posts

If the post capability_type of "page" then we add them to the list of pages that can set as a home along with the normal pages (I have used an optgroup to group them by post types) for better UI

I have not tackled the customizer UI yet or started to handle the settings/override the homepage

I would like feedback on the plan and UI

Paul

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

#31 @pbearne
4 years ago

As an extra, I am adding an error message if no pages have been published

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


4 years ago

#33 @peterwilsoncc
4 years ago

  • Keywords needs-design added

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


4 years ago

#35 @adamsilverstein
4 years ago

Hey @pbearne :) Thanks for working on this patch (for so long!) - I noticed you changed src/wp-includes/assets/script-loader-packages.php in your latest patch, is that intentional? It didn't apply cleanly so I'll leave off for my testing for now.

This ticket was mentioned in PR #524 on WordPress/wordpress-develop by adamsilverstein.


4 years ago
#36

  • Keywords has-patch added; needs-refresh removed

#37 @adamsilverstein
4 years ago

Opened a draft PR to run the test suite against the current patch.

@pbearne - are you mainly looking for feedback on the general approach? Is your code ready for testing and if so, should I apply both CustomPostTypeAsHomePages.ui.refreeh.2.patch and CustomPostTypeAsHomePages.ui.refreeh.patch ?

#38 @pbearne
4 years ago

@adamsilverstein just use the last patch

It is just the UI for setting -> reading to give you an idea of where I am going with this

to help with testing I am including code to create a book CPT in the default theme this will not be in the final patch

and the src/wp-includes/assets/script-loader-packages.php should have been patched so I have removed it

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

@pbearne
4 years ago

remove the not needed file in patch

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


4 years ago

@afercia
4 years ago

#40 follow-up: @afercia
4 years ago

  • Focuses accessibility added
  • Keywords has-screenshots added

Looking at CustomPostTypeAsHomePages.ui.refreeh.2.patch only from a UI / accessibility perspective: the markup needs improvements.

  • there are now two form elements, the radio button and the new select, wrapped within the same <label> element: this isn't okay as the form elements aren't labelled correctly
  • these two form elements need to be separated and have their own meaningful, properly associated, <label>s
  • the select element can't be used as part of the radio button labelling
  • the <label>s need to communicate what the form elements are about
  • a group of radio buttons is supposed to be used with keyboard by using the arrow keys, but now there's a select element between the two buttons: at this point I wonder whether radio buttons are the best type of form elements for this UI
  • regardless, the <label>s text needs to be changed and also be translatable: the text needs to be a fully translatable string

Something along these lines would be better:

  • Your latest posts (select the posts type below)
    • Posts type: [select element]
  • A static page (select below)

However, this wouldn't solve the problem of the select element placed between the two radio buttons.

#41 in reply to: ↑ 40 ; follow-up: @pbearne
4 years ago

Replying to afercia:

However, this wouldn't solve the problem of the select element placed between the two radio buttons.

The only way to fix that is to put the post type selector below the two radio buttons swapping it with the static homepage setting as needed

Would that work?

or does showing and hide cause more problems?

#42 in reply to: ↑ 41 @afercia
4 years ago

Replying to pbearne:

The only way to fix that is to put the post type selector below the two radio buttons swapping it with the static homepage setting as needed

Generally, show / hide can be problematic for accessibility but in this case only one of the "swapping" things needs to be used at a time. Seems an interesting idea worth exploring (pending design feedback).

#43 @hellofromTonya
3 years ago

  • Version changed from trunk to 3.3.1

This ticket predates 5.6 and therefore is not a directly attributed to trunk or 5.6 itself. Restoring its original version of 3.3.1. However, if this original version is not correct, please advise or adjust.

#44 @sabernhardt
16 months ago

  • Milestone set to Future Release

This ticket was mentioned in Slack in #accessibility by joedolson. View the logs.


15 months ago

#46 follow-up: @joedolson
15 months ago

Hey, @pbearne - do you want some help refining the UI for better accessibility on this? It seems like it's pretty well advanced, just needs some polish; but if you're still planning on working on this, it seems beneficial.

#47 in reply to: ↑ 46 @pbearne
15 months ago

Replying to joedolson:

Hey, @pbearne - do you want some help refining the UI for better accessibility on this? It seems like it's pretty well advanced, just needs some polish; but if you're still planning on working on this, it seems beneficial.

@joedolson yes I would love to get this in Happy to work on this
Do you want to have a pass at the UI?

#48 @joedolson
15 months ago

Great! I'll take a look at it. Probably not for a couple weeks, realistically.

This ticket was mentioned in Slack in #accessibility by ryokuhi. View the logs.


12 months ago

#50 @joedolson
12 months ago

So, it's been a bit more than two weeks. Something that would be really useful coming from you, @pbearne, would be a list of testing steps. I'll take a look at the UI, but we could also use some verification steps for making sure it's working as expected.

This ticket was mentioned in Slack in #accessibility by joedolson. View the logs.


4 months ago

Note: See TracTickets for help on using tickets.