Commit 464b99d173 for wordpress.org
commit 464b99d1736e48334e03dbef30b270ee0dccd2aa
Author: mcsf <mcsf@git.wordpress.org>
Date: Mon Sep 21 13:06:52 2026 +0000
Support random content redirects via ?random qarg
Add opt-in support for random content redirects, so that a page request with the `?random` query argument set will return a 302 redirect to a randomly selected published post.
The pool of eligible posts may be filtered with two additional query arguments:
- `random_post_type`
- `random_cat_id`
The feature may be opted into using:
{{{
add_filter( 'enable_random_content_redirect', '__return_true' );
}}}
Developed in: https://github.com/WordPress/wordpress-develop/pull/13022
Props mlaetitia.
Fixes #64498.
Built from https://develop.svn.wordpress.org/trunk@63767
git-svn-id: http://core.svn.wordpress.org/trunk@62939 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php
index 025a371781..c8b77e96d4 100644
--- a/wp-includes/default-filters.php
+++ b/wp-includes/default-filters.php
@@ -492,6 +492,9 @@ add_action( 'attachment_updated', 'wp_check_for_changed_slugs', 12, 3 );
add_action( 'post_updated', 'wp_check_for_changed_dates', 12, 3 );
add_action( 'attachment_updated', 'wp_check_for_changed_dates', 12, 3 );
+// Redirect random content requests (disabled by default, see 'enable_random_content_redirect').
+add_action( 'template_redirect', 'wp_random_content_redirect' );
+
// Nonce check for post previews.
add_action( 'init', '_show_post_preview' );
diff --git a/wp-includes/query.php b/wp-includes/query.php
index 42592002c1..4bcf602fd6 100644
--- a/wp-includes/query.php
+++ b/wp-includes/query.php
@@ -1239,6 +1239,122 @@ function _find_post_by_old_date( $post_type ) {
return $id;
}
+/**
+ * Redirects requests for random content to a randomly selected published post.
+ *
+ * Handles requests using the `random` query parameter, e.g. `example.com/?random`.
+ * The `random_post_type` parameter restricts the pick to a post type (default `post`),
+ * and the `random_cat_id` parameter restricts it to a category (for post types using
+ * the `category` taxonomy). Only published, non-password-protected content from
+ * viewable post types is considered, and only GET/HEAD requests are handled.
+ *
+ * Disabled by default. To enable:
+ *
+ * add_filter( 'enable_random_content_redirect', '__return_true' );
+ *
+ * @since 7.2.0
+ */
+function wp_random_content_redirect() {
+ // The `random` parameter is a flag, present with or without a value.
+ if ( ! isset( $_GET['random'] ) ) {
+ return;
+ }
+
+ /**
+ * Filters whether random content redirects are enabled.
+ *
+ * @since 7.2.0
+ *
+ * @param bool $enabled Whether `?random` requests redirect to random content. Default false.
+ */
+ if ( ! apply_filters( 'enable_random_content_redirect', false ) ) {
+ return;
+ }
+
+ $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? strtoupper( $_SERVER['REQUEST_METHOD'] ) : '';
+
+ if ( ! in_array( $request_method, array( 'GET', 'HEAD' ), true ) ) {
+ return;
+ }
+
+ $post_type = 'post';
+
+ if ( isset( $_GET['random_post_type'] ) ) {
+ $post_type = sanitize_key( wp_unslash( $_GET['random_post_type'] ) );
+ }
+
+ $post_type_object = get_post_type_object( $post_type );
+
+ if ( ! $post_type_object || ! is_post_type_viewable( $post_type_object ) ) {
+ return;
+ }
+
+ $args = array(
+ 'post_type' => $post_type,
+ 'post_status' => 'publish',
+ 'has_password' => false,
+ 'posts_per_page' => 1,
+ 'orderby' => 'ID',
+ 'order' => 'ASC',
+ 'ignore_sticky_posts' => true,
+ 'update_post_term_cache' => false,
+ 'update_post_meta_cache' => false,
+ );
+
+ if ( isset( $_GET['random_cat_id'] ) ) {
+ $cat_id = (int) wp_unslash( $_GET['random_cat_id'] );
+
+ if ( $cat_id < 1 ) {
+ return;
+ }
+
+ $args['cat'] = $cat_id;
+ }
+
+ // Pick via COUNT plus a random OFFSET rather than `ORDER BY RAND()`,
+ // which randomizes and sorts every candidate row on each request.
+ $query = new WP_Query( $args );
+ $post_count = (int) $query->found_posts;
+
+ if ( $post_count > 1 ) {
+ $offset = wp_rand( 0, $post_count - 1 );
+
+ if ( $offset > 0 ) {
+ $args['offset'] = $offset;
+ $args['no_found_rows'] = true;
+ $args['cache_results'] = false;
+
+ $query = new WP_Query( $args );
+ }
+ }
+
+ if ( empty( $query->posts ) ) {
+ return;
+ }
+
+ $link = get_permalink( $query->posts[0] );
+
+ /**
+ * Filters the random content redirect URL.
+ *
+ * Returning a falsey value cancels the redirect.
+ *
+ * @since 7.2.0
+ *
+ * @param string $link The redirect URL.
+ */
+ $link = apply_filters( 'random_content_redirect_url', $link );
+
+ if ( ! $link ) {
+ return;
+ }
+
+ // Temporary redirect, so clients and intermediary caches do not cache the randomly picked target.
+ nocache_headers();
+ wp_safe_redirect( $link, 302 );
+ exit;
+}
+
/**
* Set up global post data.
*
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 076fa84050..460931f708 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-63766';
+$wp_version = '7.2-alpha-63767';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.