Skip to content

Commit e1e75c7

Browse files
committed
feat: add mu-plugin preventing transients to be saved into database, and cleaning up existing transients from database weekly.
1 parent 321e8fe commit e1e75c7

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

default-no-transients.php

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
/*
3+
Plugin Name: No transients
4+
Version: 1.0.0
5+
Plugin URI: https://beapi.fr
6+
Author: Be API
7+
Author URI: https://beapi.fr
8+
9+
----
10+
11+
Copyright 2025 Be API Technical team ([email protected])
12+
13+
This program is free software; you can redistribute it and/or modify
14+
it under the terms of the GNU General Public License as published by
15+
the Free Software Foundation; either version 2 of the License, or
16+
(at your option) any later version.
17+
18+
This program is distributed in the hope that it will be useful,
19+
but WITHOUT ANY WARRANTY; without even the implied warranty of
20+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21+
GNU General Public License for more details.
22+
23+
You should have received a copy of the GNU General Public License
24+
along with this program; if not, write to the Free Software
25+
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26+
*/
27+
28+
namespace BeAPI;
29+
30+
if ( ! defined( 'ABSPATH' ) ) {
31+
exit;
32+
}
33+
/**
34+
* Class to prevent transients from being stored in the database
35+
* since we're using Redis for object caching
36+
*/
37+
class NoTransients {
38+
/**
39+
* Initialize the class and set up hooks
40+
*/
41+
public function __construct() {
42+
43+
44+
// Prevent transients from being retrieved
45+
add_filter( 'pre_option', [ $this, 'prevent_transient_retrieval' ], 10, 2 );
46+
47+
// Remove transients from alloptions
48+
add_filter( 'alloptions', [ $this, 'remove_transients_from_alloptions' ] );
49+
50+
// Prevent new transients from being added
51+
add_action( 'added_option', [ $this, 'delete_transient_option' ] );
52+
53+
// Prevent transients from being updated
54+
add_action( 'updated_option', [ $this, 'delete_transient_option' ] );
55+
56+
// Set up cleanup cron job
57+
add_action( 'init', [ $this, 'setup_cleanup_cron' ] );
58+
59+
// Show admin notice if no external object cache is being used
60+
add_action( 'admin_notices', [ $this, 'show_admin_notice' ] );
61+
62+
add_action( 'beapi_clean_transients', [ $this, 'cleanup_transients' ] );
63+
}
64+
65+
/**
66+
* Make transients appear expired by returning 0 for timeout options
67+
*
68+
* @param mixed $pre The pre-option value
69+
* @param string $option The option name
70+
* @return mixed The modified pre-option value
71+
*/
72+
public function prevent_transient_retrieval( $pre, $option ) {
73+
// If it's a transient timeout, return 0 to make it appear expired
74+
if ( str_starts_with( $option, '_transient_timeout' ) ) {
75+
return 0;
76+
}
77+
78+
return $pre;
79+
}
80+
81+
/**
82+
* Remove transients from alloptions array and delete them from database
83+
* This is because alloptions is called into the get_transient function, and expiration is not checked if the transient is in alloptions.
84+
*
85+
* @param array $alloptions The array of all autoloaded options
86+
* @return array The filtered options array
87+
*/
88+
public function remove_transients_from_alloptions( $alloptions ) {
89+
foreach ( $alloptions as $option => $value ) {
90+
if ( ! str_starts_with( $option, '_transient' ) ) {
91+
continue;
92+
}
93+
94+
unset( $alloptions[ $option ] );
95+
delete_option( $option );
96+
}
97+
98+
return $alloptions;
99+
}
100+
101+
/**
102+
* Delete transient options when they're added or updated
103+
*
104+
* @param string $option The option name
105+
* @param mixed $value The option value
106+
*/
107+
public function delete_transient_option( $option ) {
108+
if ( str_starts_with( $option, '_transient' ) ) {
109+
delete_option( $option );
110+
}
111+
}
112+
113+
/**
114+
* Set up weekly cron job to clean up transients
115+
*/
116+
public function setup_cleanup_cron() {
117+
if ( ! wp_next_scheduled( 'beapi_clean_transients' ) ) {
118+
wp_schedule_event( time(), 'weekly', 'beapi_clean_transients' );
119+
}
120+
}
121+
122+
/**
123+
* Clean up all transients from the database
124+
*/
125+
public function cleanup_transients() {
126+
global $wpdb;
127+
128+
// Delete all transients
129+
$wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '_transient_%'" );
130+
}
131+
132+
/**
133+
* Show admin notice if no external object cache is being used
134+
* The removal of transients when not object cache is a big performance issue
135+
*/
136+
public function show_admin_notice() {
137+
if ( wp_using_ext_object_cache() || ! current_user_can( 'manage_options' ) ) {
138+
return;
139+
}
140+
141+
echo '<div class="notice notice-error"><p style="font-size: 40px;">Beware transients are not written in database. Please remove <strong>' . esc_html( wp_basename( __FILE__ ) ) . '</strong> from the mu-plugins folder.</p></div>';
142+
}
143+
}
144+
145+
// Initialize the class
146+
new NoTransients();

0 commit comments

Comments
 (0)