PluginProbe
SQLite Object Cache / 1.6.0
SQLite Object Cache v1.6.0
1.6.5 trunk 0.1.7 1.0.0 1.1.0 1.1.1 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.4.0 1.4.1 1.5.1 1.5.4 1.5.5 1.5.6 1.5.7 All 30 releases
← All changes | includes/class-sqlite-object-cache.php +25 -156 trunk1.6.0 View file →
@@ -17,8 +17,15 @@
17 17 class SQLite_Object_Cache {
18 18 const CLEAN_EVENT_HOOK = 'sqlite_object_cache_clean';
19 19
20 20 /**
21 + * Local instance of SQLite_Object_Cache_Admin_API
22 + *
23 + * @var SQLite_Object_Cache_Admin_API|null
24 + */
25 + public $admin;
26 +
27 + /**
21 28 * Settings class object
22 29 *
23 30 * @var object
24 31 * @access public
@@ -113,9 +120,9 @@
113 120 *
114 121 * @param string $file File constructor.
115 122 * @param string $version Plugin version.
116 123 */
117 - public function __construct( $file = '', $version = '1.6.5' ) {
124 + public function __construct( $file = '', $version = '1.6.0' ) {
118 125 $this->_version = $version;
119 126 $this->_token = 'sqlite_object_cache';
120 127
121 128 // Load plugin environment variables.
@@ -127,26 +134,27 @@
127 134 $this->dropinfiledest = trailingslashit( WP_CONTENT_DIR ) . 'object-cache.php';
128 135
129 136 $this->assets_url = esc_url( trailingslashit( plugins_url( '/assets/', $this->file ) ) );
130 137
138 + $this->script_suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
139 +
131 140 register_activation_hook( $this->file, array( $this, 'on_activation' ) );
132 141 register_deactivation_hook( $this->file, array( $this, 'on_deactivation' ) );
133 142
134 143 if ( is_admin() ) {
135 - /* Suppress backups of .sqlite files if possible. */
144 + // Load API for generic admin functions.
145 + $this->admin = new SQLite_Object_Cache_Admin_API();
146 + // Suppress backups
136 147 new SQLite_Backup_Exclusion();
137 148
138 - /* Health check */
139 - new SQLite_Object_Cache_Opcache();
140 -
141 149 add_action( 'admin_notices', function () {
142 - $flushed = get_site_transient( 'sqlite-object-cache-flush-on-update' );
143 - if ( $flushed ) {
150 + $purged = get_site_transient( 'sqlite-object-cache-flush-on-update' );
151 + if ( $purged ) {
144 152 delete_site_transient( 'sqlite-object-cache-flush-on-update' );
145 - $message = __( 'Flushed the SQLite Object Cache successfully after a software installation or upgrade.', 'sqlite-object-cache' );
153 + $message = esc_html( __( 'A software installation or upgrade operation flushed the SQLite Object Cache.', 'sqlite-object-cache' ) )
146 154 ?>
147 - <div class="notice notice-success sqlite-object-cache is-dismissible">
148 - <p><?php echo esc_html( $message ); ?></p>
155 + <div class="notice notice-info sqlite-object-cache is-dismissible">
156 + <p><?php echo $message ?></p>
149 157 </div>
150 158 <?php
151 159 }
152 160 } );
@@ -163,36 +171,19 @@
163 171 wp_cache_flush();
164 172 }, 0 );
165 173
166 174
167 - /* Handle cron cache cleanup, but only on main site. */
175 + /* handle cron cache cleanup */
168 176 add_action( self::CLEAN_EVENT_HOOK, array( $this, 'clean_job' ), 10, 0 );
169 - $next_event = wp_next_scheduled( self::CLEAN_EVENT_HOOK );
170 - if ( false === $next_event && is_main_site() ) {
177 + if ( ! wp_next_scheduled( self::CLEAN_EVENT_HOOK ) ) {
171 178 wp_schedule_event( time() + HOUR_IN_SECONDS, 'hourly', self::CLEAN_EVENT_HOOK );
172 - } else if (false !== $next_event && is_multisite() && ! is_main_site() ) {
173 - wp_unschedule_event ( $next_event, self::CLEAN_EVENT_HOOK);
174 179 }
175 - /* Handle probabilistic non-cron cleanup, one request in 2500. */
176 - /* We don't need cryptographic-grade random numbering here. */
177 - // phpcs:ignore WordPress.WP.AlternativeFunctions.rand_rand
178 - if ( 1 === rand( 1, 2500 ) ) {
180 + /* Handle probabilistic non-cron cleanup, one request in 2000. */
181 + if ( 1 === rand( 1, 2000 ) ) {
179 182 add_action( 'shutdown', function () {
180 183 $this->clean_job( 1.25 );
181 184 }, 999, 0 );
182 185 }
183 -
184 - /* Admin bar flush button - works on both frontend and backend. */
185 - $option = get_option( $this->_token . '_settings', array() );
186 - if ( array_key_exists ('adminbarflush', $option ) && 'on' === $option['adminbarflush'] ) {
187 - add_action( 'init', array( $this, 'handle_admin_bar_flush' ) );
188 - add_action ( 'init', function() {
189 - if ( ! ( is_multisite() && ! is_main_site() ) && current_user_can( 'manage_options') ) {
190 - add_action( 'admin_bar_menu', array( $this, 'admin_bar_flush_button' ), 100 );
191 - add_action( 'admin_notices', array( $this, 'maybe_show_flush_notice' ) );
192 - }
193 - });
194 - }
195 186 }
196 187
197 188 /**
198 189 * WP_Cron task to clean cache entries.
@@ -201,13 +192,8 @@
201 192 *
202 193 * @return void
203 194 */
204 195 public function clean_job( $grace_factor = 1.0 ) {
205 - $current_blogid = null;
206 - if ( is_multisite() && ! is_main_site() ) {
207 - $current_blogid = get_current_blog_id();
208 - switch_to_blog( get_main_site_id() );
209 - }
210 196 $option = get_option( $this->_token . '_settings', array() );
211 197 $target_size = empty ( $option['target_size'] ) ? 16 : $option['target_size'];
212 198 $target_size *= ( 1024 * 1024 );
213 199 $threshold_size = (int) ( $target_size * $grace_factor );
@@ -238,12 +224,8 @@
238 224 }
239 225
240 226 /* Delete the least-recently-updated items to get to the target size. */
241 227 $wp_object_cache->sqlite_delete_old( $target_size, $current_size );
242 -
243 - if ( null !== $current_blogid ) {
244 - switch_to_blog ( $current_blogid );
245 - }
246 228 }
247 229
248 230 /**
249 231 * Plugin activation hook
@@ -537,22 +519,21 @@
537 519 try {
538 520 switch_to_blog( $site_id );
539 521 $this->clear_blog_transients();
540 522 } catch ( Exception $ex ) {
541 - /* Empty, intentionally. Don't crash clearing transients. */
523 + /* Avoid crashes on transient clearing */
524 + error_log( 'SQLite Object Cache problem clearing transients. Blog ' . $site_id . ':' . $ex->getMessage() );
542 525 } finally {
543 526 restore_current_blog();
544 527 }
545 528 }
546 529 // Multisite stores site transients in the sitemeta table.
547 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
548 530 $wpdb->query(
549 531 $wpdb->prepare(
550 - "DELETE FROM {$wpdb->sitemeta} WHERE a.meta_key LIKE %s",
532 + "DELETE FROM {$wpdb->sitemeta} WHERE a.meta_key LIKE %s",
551 533 $wpdb->esc_like( '_site_transient_' ) . '%'
552 534 )
553 535 );
554 -
555 536 }
556 537 }
557 538
558 539 /**
@@ -563,9 +544,8 @@
563 544 * @return void
564 545 */
565 546 private function clear_blog_transients( $tag = '_transient_') {
566 547 global $wpdb;
567 - // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
568 548 $wpdb->query(
569 549 $wpdb->prepare(
570 550 "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
571 551 $wpdb->esc_like( $tag ) . '%'
@@ -620,118 +600,7 @@
620 600 update_option( $this->_token . '_settings', $option, true );
621 601 }
622 602
623 603 return $target_use_apcu;
624 - }
625 -
626 - /**
627 - * Add a flush button to the admin bar.
628 - *
629 - * @param WP_Admin_Bar $wp_admin_bar The admin bar instance.
630 - *
631 - * @return void
632 - */
633 - public function admin_bar_flush_button( $wp_admin_bar ) {
634 - if ( ! is_admin_bar_showing() ) {
635 - return;
636 - }
637 -
638 - if ( ! current_user_can( 'manage_options' ) ) {
639 - return;
640 - }
641 -
642 - // Only show on main site for multisite installations.
643 - if ( is_multisite() && ! is_main_site() ) {
644 - return;
645 - }
646 -
647 - $flush_url = add_query_arg(
648 - array( 'sqlite_object_cache_action' => 'flush' ),
649 - remove_query_arg( 'sqlite_object_cache_action' )
650 - );
651 - $nonced_url = wp_nonce_url( $flush_url, 'sqlite_object_cache_flush' );
652 -
653 - $wp_admin_bar->add_node(
654 - array(
655 - 'id' => 'sqlite-object-cache-flush',
656 - 'title' => __( 'Flush Object Cache', 'sqlite-object-cache' ),
657 - 'href' => $nonced_url,
658 - 'meta' => array(
659 - 'title' => __( 'Delete all object cache entries now, including all transients.', 'sqlite-object-cache' ),
660 - ),
661 - )
662 - );
663 - }
664 -
665 - /**
666 - * Handle the admin bar flush action.
667 - *
668 - * @return void
669 - */
670 - public function handle_admin_bar_flush() {
671 - if ( ! isset( $_GET['sqlite_object_cache_action'] ) ) {
672 - return;
673 - }
674 -
675 - $action = sanitize_key( wp_unslash( $_GET['sqlite_object_cache_action'] ) );
676 -
677 - if ( 'flush' !== $action ) {
678 - return;
679 - }
680 -
681 - if ( ! current_user_can( 'manage_options' ) ) {
682 - wp_die( esc_html__( 'You do not have permission to flush the object cache.', 'sqlite-object-cache' ) );
683 - }
684 -
685 - // Only allow flush on main site for multisite installations (matches button visibility).
686 - if ( is_multisite() && ! is_main_site() ) {
687 - wp_die( esc_html__( 'Cache flush is only available on the main site.', 'sqlite-object-cache' ) );
688 - }
689 -
690 - check_admin_referer( 'sqlite_object_cache_flush' );
691 -
692 - wp_cache_flush();
693 -
694 - // Use a user-specific transient so only the initiating user sees the flush notice (applies to both single-site and multisite).
695 - $transient_key = 'sqlite_object_cache_flushed_' . get_current_user_id();
696 - set_transient( $transient_key, true, 30 );
697 -
698 - $referer = wp_get_referer();
699 - if ( $referer ) {
700 - $redirect_url = $referer;
701 - } else {
702 - $redirect_url = is_admin() ? admin_url() : home_url();
703 - }
704 - // Remove action and nonce query parameters from URL.
705 - $redirect_url = remove_query_arg( array( 'sqlite_object_cache_action', '_wpnonce' ), $redirect_url );
706 -
707 - wp_safe_redirect( $redirect_url );
708 - exit;
709 - }
710 -
711 - /**
712 - * Check for flush transient and show notice if set.
713 - *
714 - * @return void
715 - */
716 - public function maybe_show_flush_notice() {
717 - $transient_key = 'sqlite_object_cache_flushed_' . get_current_user_id();
718 - if ( get_transient( $transient_key ) ) {
719 - delete_transient( $transient_key );
720 - $this->show_flush_notice();
721 - }
722 - }
723 -
724 - /**
725 - * Display a notice when the object cache was flushed via admin bar.
726 - *
727 - * @return void
728 - */
729 - public function show_flush_notice() {
730 - ?>
731 - <div class="notice notice-success sqlite-object-cache is-dismissible">
732 - <p><?php esc_html_e( 'SQLite Object Cache flushed successfully.', 'sqlite-object-cache' ); ?></p>
733 - </div>
734 - <?php
735 604 }
736 605
737 606 }