Skip to content

Commit 757cb9c

Browse files
committed
Rewrite Rules: Add support for random content redirects.
Introduce a `random` query var and `/random/` rewrite rules[1], built on the existing rewrite, WP, and query APIs, that redirect to a randomly selected published post. Random requests[2] work for the whole site, taxonomy terms, authors and post type archives, with the base configurable on the Permalinks screen. A new `randomable` post type argument controls which content is eligible, and the selection runs through the main query so it remains filterable and costs a single database query. The Random Base[3] is translatable and stored in the rewrite rules. This means that rewrite rules are regenerated when translations are updated or the Site Language is changed. Also, if a post or page is published that would result in the same slug as the Random Base, that content gets priority and nothing will be random[4]. This reintroduces the feature committed in r63767 and reverted in r63906. 1) Literally `/random/`, not just rules that are random. Though that could be fun too! 2) Not "random" as in unpredictable, but random as in someone wanted it to be random. 3) It's intentionally "random" but it could also intentionally be "aleatoria" or "karkovice". 4) The other random permalinks will still work, so not nothing. But is anything really random? Developed in: #14018 Follow-up to r63767, r63906. Props jorbin, peterwilsoncc, westonruter, mukesh27, annezazu, mlaetitia, mcsf, johnbillion, TobiasBg, solankisoftware, sajib1223, ellatrix, matt. See #64498. git-svn-id: https://develop.svn.wordpress.org/trunk@64402 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 78ff858 commit 757cb9c

20 files changed

Lines changed: 4180 additions & 16 deletions

‎src/wp-admin/includes/schema.php‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,9 @@ function populate_options( array $options = array() ) {
563563

564564
// 6.9.0
565565
'wp_notes_notify' => 1,
566+
567+
// 7.2.0
568+
'wp_random_base' => '',
566569
);
567570

568571
// 3.3.0

‎src/wp-admin/includes/upgrade.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2892,7 +2892,7 @@ function __get_option( $setting ) { // phpcs:ignore WordPress.NamingConventions.
28922892
return __get_option( 'siteurl' );
28932893
}
28942894

2895-
if ( in_array( $setting, array( 'siteurl', 'home', 'category_base', 'tag_base' ), true ) ) {
2895+
if ( in_array( $setting, array( 'siteurl', 'home', 'category_base', 'tag_base', 'wp_random_base' ), true ) ) {
28962896
$option = untrailingslashit( $option );
28972897
}
28982898

‎src/wp-admin/network/site-settings.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
'permalink_structure',
163163
'category_base',
164164
'tag_base',
165+
'wp_random_base',
165166
'upload_path',
166167
'upload_url_path',
167168
);

‎src/wp-admin/options-permalink.php‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
get_current_screen()->set_help_sidebar( $help_sidebar_content );
7070
unset( $help_sidebar_content );
7171

72+
/** @global WP_Rewrite $wp_rewrite WordPress rewrite component. */
73+
global $wp_rewrite;
74+
7275
$home_path = get_home_path();
7376
$iis7_permalinks = iis7_supports_permalinks();
7477
$permalink_structure = get_option( 'permalink_structure' );
@@ -94,6 +97,8 @@
9497

9598
$category_base = get_option( 'category_base' );
9699
$tag_base = get_option( 'tag_base' );
100+
$random_base = get_option( 'wp_random_base' );
101+
$random_base = is_string( $random_base ) ? $random_base : '';
97102

98103
$structure_updated = false;
99104
$htaccess_update_required = false;
@@ -144,6 +149,16 @@
144149

145150
$wp_rewrite->set_tag_base( $tag_base );
146151
}
152+
153+
if ( wp_is_random_content_redirect_enabled() && isset( $_POST['wp_random_base'] ) && is_string( $_POST['wp_random_base'] ) ) {
154+
$random_base = $_POST['wp_random_base'];
155+
156+
if ( ! empty( $random_base ) ) {
157+
$random_base = $blog_prefix . preg_replace( '#/+#', '/', '/' . str_replace( '#', '', $random_base ) );
158+
}
159+
160+
$wp_rewrite->set_random_base( $random_base );
161+
}
147162
}
148163

149164
if ( $iis7_permalinks ) {
@@ -236,6 +251,7 @@
236251
$permalink_structure = preg_replace( '|^/?blog|', '', $permalink_structure );
237252
$category_base = preg_replace( '|^/?blog|', '', $category_base );
238253
$tag_base = preg_replace( '|^/?blog|', '', $tag_base );
254+
$random_base = preg_replace( '|^/?blog|', '', $random_base ) ?? '';
239255
}
240256

241257
$url_base = home_url( $blog_prefix . $index_php_prefix );
@@ -457,6 +473,29 @@ class="button button-secondary"
457473
<?php endif; ?>
458474
</td>
459475
</tr>
476+
<?php if ( wp_is_random_content_redirect_enabled() ) : ?>
477+
<tr>
478+
<th>
479+
<label for="wp_random_base">
480+
<?php _e( 'Random base' ); ?>
481+
</label>
482+
</th>
483+
<td>
484+
<?php if ( '' === $blog_prefix ) : ?>
485+
<input name="wp_random_base" id="wp_random_base" type="text"
486+
value="<?php echo esc_attr( $random_base ); ?>" class="regular-text code"
487+
/>
488+
<?php else : ?>
489+
<span class="code permalink-structure-has-blog-prefix">
490+
<code class="no-break"><?php echo $blog_prefix; ?></code>
491+
<input name="wp_random_base" id="wp_random_base" type="text"
492+
value="<?php echo esc_attr( $random_base ); ?>" class="regular-text code"
493+
/>
494+
</span>
495+
<?php endif; ?>
496+
</td>
497+
</tr>
498+
<?php endif; ?>
460499
<?php do_settings_fields( 'permalink', 'optional' ); ?>
461500
</table>
462501

‎src/wp-includes/class-wp-post-type.php‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@ final class WP_Post_Type {
123123
*/
124124
public $embeddable = null;
125125

126+
/**
127+
* Whether posts of this post type can be selected by random content redirects.
128+
*
129+
* Random content redirects send requests such as `example.com/random/` to a
130+
* randomly selected post.
131+
*
132+
* Default is true when $publicly_queryable is true and the post type has an archive.
133+
*
134+
* @since 7.2.0
135+
* @var bool $randomable
136+
*/
137+
public $randomable = null;
138+
126139
/**
127140
* Whether to generate and allow a UI for managing this post type in the admin.
128141
*
@@ -546,6 +559,7 @@ public function set_props( $args ) {
546559
'exclude_from_search' => null,
547560
'publicly_queryable' => null,
548561
'embeddable' => null,
562+
'randomable' => null,
549563
'show_ui' => null,
550564
'show_in_menu' => null,
551565
'show_in_nav_menus' => null,
@@ -590,6 +604,9 @@ public function set_props( $args ) {
590604
// If not set, default to the setting for 'public'.
591605
$args['embeddable'] ??= $args['public'];
592606

607+
// If not set, default to publicly queryable post types with an archive.
608+
$args['randomable'] ??= $args['publicly_queryable'] && (bool) $args['has_archive'];
609+
593610
// If not set, default rest_namespace to wp/v2 if show_in_rest is true.
594611
if ( false === $args['rest_namespace'] && ! empty( $args['show_in_rest'] ) ) {
595612
$args['rest_namespace'] = 'wp/v2';

‎src/wp-includes/class-wp-query.php‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,16 @@ class WP_Query {
417417
*/
418418
public bool $is_sitemap = false;
419419

420+
/**
421+
* Signifies whether the current query is for random content.
422+
*
423+
* True for a blog home, archive or search request that includes the `random`
424+
* query variable, for example `example.com/random/` or `example.com/?s=foo&random`.
425+
*
426+
* @since 7.2.0
427+
*/
428+
public bool $is_random = false;
429+
420430
/**
421431
* Signifies whether the current query is for the page_for_posts page.
422432
*
@@ -527,6 +537,7 @@ private function init_query_flags() {
527537
$this->is_robots = false;
528538
$this->is_favicon = false;
529539
$this->is_sitemap = false;
540+
$this->is_random = false;
530541
$this->is_posts_page = false;
531542
$this->is_post_type_archive = false;
532543
}
@@ -1147,6 +1158,10 @@ public function parse_query( $query = '' ) {
11471158

11481159
$this->is_embed = $this->is_embed && ( $this->is_singular || $this->is_404 );
11491160

1161+
$this->is_random = isset( $query_vars['random'] )
1162+
&& ! $this->is_feed
1163+
&& ( $this->is_home || $this->is_archive || $this->is_search );
1164+
11501165
$this->query_vars_hash = md5( serialize( $this->query_vars ) );
11511166
$this->query_vars_changed = false;
11521167

@@ -4653,6 +4668,19 @@ public function is_sitemap(): bool {
46534668
return $this->is_sitemap;
46544669
}
46554670

4671+
/**
4672+
* Determines whether the query is for random content.
4673+
*
4674+
* @since 7.2.0
4675+
*
4676+
* @see wp_is_random_content_query()
4677+
*
4678+
* @return bool Whether the query is for random content.
4679+
*/
4680+
public function is_random(): bool {
4681+
return $this->is_random;
4682+
}
4683+
46564684
/**
46574685
* Determines whether the query is for a search.
46584686
*

0 commit comments

Comments
 (0)