PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | modules/theme-tools/random-redirect.php +103 -66 13.2.416.3-a.1 View file →
@@ -12,90 +12,127 @@
12 12 */
13 13
14 14 // phpcs:disable WordPress.Security.NonceVerification -- No changes to the site here, it just redirects.
15 15
16 -/**
17 - * Redirects to a random post on the site.
16 +/*
17 + * This module was removed from the plugin in 13.6 and restored in 16.1. In the meantime some themes
18 + * and plugins started shipping their own copy of the function below, so only declare it when nothing
19 + * else has, to avoid a fatal error. The declaration must stay inside this conditional: PHP binds
20 + * unconditional top-level function declarations when the file is compiled, before any check could run.
18 21 */
19 -function jetpack_matt_random_redirect() {
20 - // Verify that the Random Redirect plugin this code is from is not active
21 - // See https://plugins.trac.wordpress.org/ticket/1898
22 - if ( ! ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
23 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
24 - if ( is_plugin_active( 'random-redirect/random-redirect.php' ) ) {
22 +if ( ! function_exists( 'jetpack_matt_random_redirect' ) ) {
23 + /**
24 + * Redirects to a random post on the site.
25 + */
26 + function jetpack_matt_random_redirect() {
27 + /**
28 + * Allows disabling the random redirect feature.
29 + *
30 + * @since 16.1
31 + *
32 + * @param bool $enabled Whether the random redirect feature is enabled. Default true.
33 + */
34 + if ( ! apply_filters( 'jetpack_random_redirect_enabled', true ) ) {
25 35 return;
26 36 }
27 - }
28 37
29 - // Acceptable URL formats: /[...]/?random=[post type], /?random, /&random, /&random=1
30 - if ( ! isset( $_GET['random'] ) && ! ( isset( $_SERVER['REQUEST_URI'] ) && in_array( strtolower( $_SERVER['REQUEST_URI'] ), array( '/&random', '/&random=1' ), true ) ) ) {
31 - return;
32 - }
38 + // Verify that the Random Redirect plugin this code is from is not active
39 + // See https://plugins.trac.wordpress.org/ticket/1898
40 + if ( ! ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ) {
41 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
42 + if ( is_plugin_active( 'random-redirect/random-redirect.php' ) ) {
43 + return;
44 + }
45 + }
33 46
34 - // Ignore POST requests.
35 - if ( ! empty( $_POST ) ) {
36 - return;
37 - }
47 + // Acceptable URL formats: /[...]/?random=[post type], /?random, /&random, /&random=1
48 + if ( ! isset( $_GET['random'] ) && ! ( isset( $_SERVER['REQUEST_URI'] ) && in_array( strtolower( $_SERVER['REQUEST_URI'] ), array( '/&random', '/&random=1' ), true ) ) ) {
49 + return;
50 + }
38 51
39 - // Persistent AppEngine abuse. ORDER BY RAND is expensive.
40 - if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && strstr( filter_var( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ), 'AppEngine-Google' ) ) {
41 - wp_die( 'Please <a href="https://en.support.wordpress.com/contact/" rel="noopener noreferrer" target="_blank">contact support</a>' );
42 - }
52 + // Ignore POST requests.
53 + if ( ! empty( $_POST ) ) {
54 + return;
55 + }
43 56
44 - $where = array(
45 - "post_password = ''",
46 - "post_status = 'publish'",
47 - );
48 - $where_args = array();
57 + // Persistent AppEngine abuse. ORDER BY RAND is expensive.
58 + if ( isset( $_SERVER['HTTP_USER_AGENT'] ) && strstr( filter_var( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ), 'AppEngine-Google' ) ) {
59 + wp_die( 'Please <a href="https://en.support.wordpress.com/contact/" rel="noopener noreferrer" target="_blank">contact support</a>' );
60 + }
49 61
50 - // Set default post type.
51 - $post_type = get_post_type();
62 + $where = array(
63 + "post_password = ''",
64 + "post_status = 'publish'",
65 + );
66 + $where_args = array();
52 67
53 - // Change the post type if the parameter is set.
54 - if ( isset( $_GET['random_post_type'] ) && post_type_exists( sanitize_key( $_GET['random_post_type'] ) ) ) {
55 - $post_type = sanitize_key( $_GET['random_post_type'] );
56 - }
68 + // Set default post type.
69 + $post_type = get_post_type();
57 70
58 - // Don't show a random page if 'page' isn't specified as the post type specifically.
59 - if ( 'page' === $post_type && is_front_page() && ! isset( $_GET['random_post_type'] ) ) {
60 - $post_type = 'post';
61 - }
71 + // Change the post type if the parameter is set.
72 + if ( isset( $_GET['random_post_type'] ) && post_type_exists( sanitize_key( $_GET['random_post_type'] ) ) ) {
73 + $post_type = sanitize_key( $_GET['random_post_type'] );
74 + }
62 75
63 - $where[] = 'p.post_type = %s';
64 - $where_args[] = $post_type;
76 + // Don't show a random page if 'page' isn't specified as the post type specifically.
77 + if ( 'page' === $post_type && is_front_page() && ! isset( $_GET['random_post_type'] ) ) {
78 + $post_type = 'post';
79 + }
65 80
66 - // Set author name if we're on an author archive.
67 - if ( is_author() ) {
68 - $where[] = 'post_author = %s';
69 - $where_args[] = get_the_author_meta( 'ID' );
70 - }
81 + $where[] = 'p.post_type = %s';
82 + $where_args[] = $post_type;
71 83
72 - // Set default category type
73 - if ( is_category() ) {
74 - $category = get_the_category();
75 - if ( isset( $category ) && ! empty( $category ) ) {
76 - $random_cat_id = $category[0]->term_id;
84 + // Set author name if we're on an author archive.
85 + if ( is_author() ) {
86 + $where[] = 'post_author = %s';
87 + $where_args[] = get_the_author_meta( 'ID' );
77 88 }
78 - }
79 89
80 - // Set the category ID if the parameter is set.
81 - if ( isset( $_GET['random_cat_id'] ) ) {
82 - $random_cat_id = (int) $_GET['random_cat_id'];
83 - }
90 + // Set default category type
91 + if ( is_category() ) {
92 + $category = get_the_category();
93 + if ( isset( $category ) && ! empty( $category ) ) {
94 + $random_cat_id = $category[0]->term_id;
95 + }
96 + }
84 97
85 - global $wpdb;
98 + // Set the category ID if the parameter is set.
99 + if ( isset( $_GET['random_cat_id'] ) ) {
100 + $random_cat_id = (int) $_GET['random_cat_id'];
101 + }
86 102
87 - $where = implode( ' AND ', $where );
88 - if ( isset( $random_cat_id ) ) {
89 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
90 - $random_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT ID FROM $wpdb->posts AS p INNER JOIN $wpdb->term_relationships AS tr ON (p.ID = tr.object_id AND tr.term_taxonomy_id = %s) INNER JOIN $wpdb->term_taxonomy AS tt ON(tr.term_taxonomy_id = tt.term_taxonomy_id AND taxonomy = 'category') WHERE $where ORDER BY RAND() LIMIT 1", $random_cat_id, ...$where_args ) );
91 - } else {
92 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
93 - $random_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts AS p WHERE $where ORDER BY RAND() LIMIT 1", ...$where_args ) );
103 + global $wpdb;
104 +
105 + $where = implode( ' AND ', $where );
106 +
107 + // Pick a post via COUNT plus a random OFFSET rather than ORDER BY RAND(), which randomizes and sorts every candidate row on each request.
108 + if ( isset( $random_cat_id ) ) {
109 + $from_where = "FROM $wpdb->posts AS p INNER JOIN $wpdb->term_relationships AS tr ON (p.ID = tr.object_id AND tr.term_taxonomy_id = %s) INNER JOIN $wpdb->term_taxonomy AS tt ON(tr.term_taxonomy_id = tt.term_taxonomy_id AND taxonomy = 'category') WHERE $where";
110 + $query_args = array_merge( array( $random_cat_id ), $where_args );
111 + } else {
112 + $from_where = "FROM $wpdb->posts AS p WHERE $where";
113 + $query_args = $where_args;
114 + }
115 +
116 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
117 + $post_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( DISTINCT p.ID ) $from_where", ...$query_args ) );
118 +
119 + if ( $post_count < 1 ) {
120 + return;
121 + }
122 +
123 + $query_args[] = wp_rand( 0, $post_count - 1 );
124 + // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
125 + $random_id = $wpdb->get_var( $wpdb->prepare( "SELECT DISTINCT p.ID $from_where ORDER BY p.ID LIMIT 1 OFFSET %d", ...$query_args ) );
126 +
127 + if ( ! $random_id ) {
128 + return;
129 + }
130 +
131 + // @phan-suppress-next-line PhanTypeMismatchArgument
132 + $permalink = get_permalink( $random_id );
133 + wp_safe_redirect( $permalink );
134 + exit( 0 );
94 135 }
95 136
96 - $permalink = get_permalink( $random_id );
97 - wp_safe_redirect( $permalink );
98 - exit;
137 + add_action( 'template_redirect', 'jetpack_matt_random_redirect' );
99 138 }
100 -
101 -add_action( 'template_redirect', 'jetpack_matt_random_redirect' );