Skip to content

Instantly share code, notes, and snippets.

@westonruter
Last active March 25, 2017 04:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save westonruter/5e8fc5b2a972392d85af4d7befcbb8da to your computer and use it in GitHub Desktop.
Save westonruter/5e8fc5b2a972392d85af4d7befcbb8da to your computer and use it in GitHub Desktop.
<?php
/**
* Plugin Name: WP Trac #39254: Allow starter content posts to display in The Loop
* Version: 0.1.0
* Author: Weston Ruter, XWP
* Plugin URI: https://core.trac.wordpress.org/ticket/39254
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 or, at
* your discretion, any later version, as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* @package WordPress
*/
/**
* Class WP_Trac_39254
*
* The methods in this class would likely go into `WP_Customize_Nav_Menus`,
* perhaps replacing the `make_auto_draft_status_previewable` method.
*
* @see WP_Customize_Nav_Menus::make_auto_draft_status_previewable()
*/
class WP_Trac_39254 {
/**
* Auto draft post IDs in the current changeset.
*
* @var array
*/
protected $changeset_auto_draft_post_ids = array();
/**
* Constructor.
*/
function __construct() {
add_action( 'customize_preview_init', array( $this, 'make_auto_draft_post_stubs_queryable' ) );
}
/**
* Add hooks to ensure auto-draft posts from the current changeset are included in WP_Query results.
*
* @param WP_Customize_Manager $wp_customize Manager.
*/
function make_auto_draft_post_stubs_queryable( WP_Customize_Manager $wp_customize ) {
global $wp_post_statuses;
// WordPress 4.7 required.
if ( ! method_exists( $wp_customize, 'changeset_data' ) ) {
return;
}
/*
* Note that we cannot use $wp_customize->get_setting( 'nav_menus_created_posts' )->value()
* for the sake of unauthenticated users who may be previewing the changeset on the
* frontend. The WP_Customize_Nav_Menus::sanitize_nav_menus_created_posts() function
* removes IDs from the list for which the current user cannot edit.
*/
$changeset_data = $wp_customize->changeset_data();
if ( isset( $changeset_data['nav_menus_created_posts']['value'] ) && is_array( $changeset_data['nav_menus_created_posts']['value'] ) ) {
$this->changeset_auto_draft_post_ids = array_merge(
$this->changeset_auto_draft_post_ids,
$changeset_data['nav_menus_created_posts']['value']
);
}
/*
* Now merge the starter content post IDs from the changeset with any additional
* IDs for page/post stubs created for nav menus which may not have been written
* into the changeset yet (which are still being sent in POST data).
*/
$nav_menus_created_posts_setting = $wp_customize->get_setting( 'nav_menus_created_posts' );
if ( $nav_menus_created_posts_setting ) {
$this->changeset_auto_draft_post_ids = array_merge(
$this->changeset_auto_draft_post_ids,
$nav_menus_created_posts_setting->value()
);
}
// If there are no auto-draft posts in the current changeset, then there is nothing to do here.
if ( empty( $this->changeset_auto_draft_post_ids ) ) {
return;
}
/*
* Ensure that starter content posts (with auto-draft status) will be considered
* to have a public post status in in WP_Query::get_posts(), at:
* https://github.com/WordPress/wordpress-develop/blob/4.7.3/src/wp-includes/class-wp-query.php#L2351-L2357
* Compare this with WP_Customize_Nav_Menus::make_auto_draft_status_previewable(),
* which apparently did not go far enough.
*/
$wp_post_statuses['auto-draft']->public = true;
add_action( 'pre_get_posts', array( $this, 'prevent_filter_suppression' ), 100, 2 );
add_filter( 'posts_where', array( $this, 'filter_posts_where_to_include_post_stubs' ) );
}
/**
* Make sure that the posts_where filter will be applied.
*
* @param WP_Query $query The WP_Query instance.
*/
function prevent_filter_suppression( WP_Query $query ) {
$query->set( 'suppress_filters', false );
}
/**
* Filter SQL WHERE clause for posts queries to exclude auto-draft posts that aren't part of the current changeset.
*
* @param string $where The WHERE clause of the query.
* @return string Amended SQL WHERE.
*/
function filter_posts_where_to_include_post_stubs( $where ) {
global $wpdb;
/*
* This could be improved if WP_Query::get_posts() would allow for the
* post statuses to be queried to be individually filtered before it is
* added to the WHERE string for filtering. Perhaps there could be a
* `posts_where_statuses` filter which was passed an array of the
* conditions before they are AND'ed together.
* See https://github.com/WordPress/wordpress-develop/blob/4.7.3/src/wp-includes/class-wp-query.php#L2289-L2376
*/
$old_condition = "{$wpdb->posts}.post_status = 'publish'";
$new_condition = "( $old_condition OR ( ";
$new_condition .= "{$wpdb->posts}.post_status = 'auto-draft' ";
$new_condition .= ' AND ';
$new_condition .= sprintf(
"{$wpdb->posts}.ID IN ( %s )",
join( ', ', array_map( 'intval', $this->changeset_auto_draft_post_ids ) )
);
$new_condition .= '))';
// @todo This is somewhat brittle.
$where = str_replace( $old_condition, $new_condition, $where );
return $where;
}
}
$wp_trac_39254_plugin = new WP_Trac_39254();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment