-
-
Save gaambo/d4723975b7de3d282c5da76c3b8521d2 to your computer and use it in GitHub Desktop.
wordpress events post type with future post_dates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Making future/scheduled posts publicly available is done like this: | |
// 1. Store event date in post_date field (may be in future) | |
// 2. Save. WordPress automatically sets status to 'future' | |
// if the "wished" status is 'published' and the date is in future | |
// 3. WordPress triggers a post_transition hook for the future post status | |
// 4. WordPress normally would schedule a cron event to publish the post - this is removed | |
// 5. Instead on transitioning to future we publish the post (= force status to publish) | |
// This works, by using wp_publish_post because this only changes the status in the database | |
// but keeps the post_date | |
remove_action('future_' . POST_TYPE, '_future_post_hook'); | |
add_action('future_' . POST_TYPE, __NAMESPACE__ . '\publishScheduledPost', 10, 3); | |
add_action('pre_get_posts', __NAMESPACE__ . '\showFuturePosts'); | |
add_filter('query_vars', __NAMESPACE__ . '\registerCustomQueryVars'); | |
function showFuturePosts(WP_Query $query) | |
{ | |
if (is_admin()) { | |
return; | |
} | |
$postType = (array)$query->get('post_type'); | |
if (!in_array(POST_TYPE, $postType)) { | |
return; | |
} | |
// | |
// 1. Handle future/publish post status | |
// | |
$queriedStatus = $query->get('post_status'); | |
// If want to display published posts only -> show future posts as well. | |
if (empty($queriedStatus) || $queriedStatus === 'publish') { | |
$query->set('post_status', ['publish', 'future']); | |
} elseif (is_array($queriedStatus) && in_array('publish', $queriedStatus)) { | |
// If filters on post_status are enabled, check if publish is in them | |
// then add future as well. | |
$query->set('post_status', [...$queriedStatus, 'future']); | |
} | |
// | |
// 2. Handle custom "scope" query arg which allows showing only future ore past events in custom queries and filters. | |
// | |
$scope = $query->get('event_scope'); | |
if (!empty($scope)) { | |
$oldDateQuery = $query->get('date_query'); | |
$oldDateQuery = !is_array($oldDateQuery) || empty($oldDateQuery) ? [] : $oldDateQuery; | |
$newDateQuery = []; | |
if ($scope === 'past') { | |
$newDateQuery['before'] = current_time('Y-m-d'); | |
} elseif ($scope === 'future') { | |
$newDateQuery['after'] = date('Y-m-d', strtotime('-1 day', current_time('U'))); // after yesterday | |
} | |
if (!empty($newDateQuery)) { | |
$newDateQuery = array_merge($oldDateQuery, $newDateQuery); | |
$query->set('date_query', $newDateQuery); | |
} | |
} | |
} | |
/** | |
* Force publishes a scheduled post | |
* See comment at top of the file | |
* | |
* No need to check for post type, because this is hooked to a post status + post type specific action | |
* | |
* @param int $postId | |
* @param WP_Post $post | |
* @param string $oldStatus | |
* @return void | |
*/ | |
function publishScheduledPost(int $postId, WP_Post $post, string $oldStatus): void | |
{ | |
if ($oldStatus === 'publish' || $oldStatus === 'future') { | |
wp_publish_post($postId); | |
} | |
} | |
function registerCustomQueryVars(array $queryVars): array | |
{ | |
$queryVars[] = 'event_scope'; | |
return $queryVars; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment