PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 14.1.1 14.2.2 All 502 releases
jetpack / modules / theme-tools / random-redirect.php

random-redirect.php in Jetpack – WP Security, Backup, Speed, & Growth 16.2, at modules/theme-tools/random-redirect.php

139 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Random Redirect
4 * Plugin URI: https://wordpress.org/extend/plugins/random-redirect/
5 * Description: Allows you to create a link to yourblog.example.com/?random which will redirect someone to a random post on your blog, in a StumbleUpon-like fashion.
6 * Version: 1.2-wpcom
7 * Author: Matt Mullenweg
8 * Author URI: https://ma.tt/
9 * Text Domain: jetpack
10 *
11 * @package automattic/jetpack
12 */
13
14 // phpcs:disable WordPress.Security.NonceVerification -- No changes to the site here, it just redirects.
15
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.
21 */
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 ) ) {
35 return;
36 }
37
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 }
46
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 }
51
52 // Ignore POST requests.
53 if ( ! empty( $_POST ) ) {
54 return;
55 }
56
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 }
61
62 $where = array(
63 "post_password = ''",
64 "post_status = 'publish'",
65 );
66 $where_args = array();
67
68 // Set default post type.
69 $post_type = get_post_type();
70
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 }
75
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 }
80
81 $where[] = 'p.post_type = %s';
82 $where_args[] = $post_type;
83
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' );
88 }
89
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 }
97
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 }
102
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 );
135 }
136
137 add_action( 'template_redirect', 'jetpack_matt_random_redirect' );
138 }
139