Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 88 additions & 8 deletions src/class-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ public static function get_instance() {
* @return void
*/
public function register_hooks() {
$this->accessed_options = \get_option( 'option_optimizer', [ 'used_options' => [] ] )['used_options'];

// Hook into all actions and filters to monitor option accesses.
// @phpstan-ignore-next-line -- The 'all' hook does not need a return.
\add_filter( 'all', [ $this, 'monitor_option_accesses' ] );
Expand Down Expand Up @@ -125,23 +123,105 @@ protected function add_option_usage( $option_name ) {
/**
* Update the 'option_optimizer' option with the list of used options at the end of the page load.
*
* Uses transient batching to reduce database writes - only flushes to the main option
* every 5 minutes instead of on every request.
*
* @return void
*/
public function update_tracked_options() {
// phpcs:ignore WordPress.Security.NonceVerification -- not doing anything.
if ( isset( $_GET['page'] ) && $_GET['page'] === 'aaa-option-optimizer' ) {
return;
}
// Retrieve the existing option_optimizer data.
$option_optimizer = get_option( 'option_optimizer', [ 'used_options' => [] ] );

$option_optimizer['used_options'] = $this->accessed_options;

// Handle reset: clear batch and main option.
if ( $this->should_reset ) {
\delete_transient( 'option_optimizer_batch' );

$option_optimizer = \get_option( 'option_optimizer', [ 'used_options' => [] ] );
$option_optimizer['used_options'] = [];
\update_option( 'option_optimizer', $option_optimizer, false );
return;
}

// Get the batch data.
$batch_data = $this->get_batch_data();

// Add current request's options to the batch.
foreach ( $this->accessed_options as $option_name => $count ) {
if ( ! isset( $batch_data['options'][ $option_name ] ) ) {
$batch_data['options'][ $option_name ] = 0;
}
$batch_data['options'][ $option_name ] += $count;
}

// Check if it's time to flush the batch.
$should_flush = ( \time() - $batch_data['last_flush'] ) >= $this->get_flush_interval();

// Flush batch to main option every 5 minutes.
if ( ! empty( $batch_data['options'] ) && $should_flush ) {
$this->flush_batch_to_option( $batch_data['options'] );

// Reset the batch data.
$batch_data = [
'options' => [],
'last_flush' => \time(),
];
}

// No expiry - batch is explicitly deleted on flush, expiry would only cause data loss.
\set_transient( 'option_optimizer_batch', $batch_data, 0 );
}

/**
* Get the batch data.
*
* @return array<string, int>
*/
protected function get_batch_data() {
// Get existing batch (stores both data and flush timestamp in one transient).
$batch_data = \get_transient( 'option_optimizer_batch' );
if ( ! \is_array( $batch_data ) || ! isset( $batch_data['options'], $batch_data['last_flush'] ) ) {
$batch_data = [
'options' => [],
'last_flush' => \time(),
];
}

return $batch_data;
}

/**
* Get the flush interval.
*
* @return int
*/
protected function get_flush_interval() {
return (int) \apply_filters( 'aaa_option_optimizer_flush_interval', 5 * MINUTE_IN_SECONDS );
}

/**
* Flush the batched data to the main option_optimizer option.
*
* @param array<string, int> $batch The batched option usage data.
*
* @return void
*/
protected function flush_batch_to_option( $batch ) {

if ( empty( $batch ) ) {
return;
}

$option_optimizer = \get_option( 'option_optimizer', [ 'used_options' => [] ] );

foreach ( $batch as $option_name => $count ) {
if ( ! isset( $option_optimizer['used_options'][ $option_name ] ) ) {
$option_optimizer['used_options'][ $option_name ] = 0;
}
$option_optimizer['used_options'][ $option_name ] += $count;
}

// Update the 'option_optimizer' option with the new list.
update_option( 'option_optimizer', $option_optimizer, false );
\update_option( 'option_optimizer', $option_optimizer, false );
}
}
3 changes: 3 additions & 0 deletions uninstall.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@
exit;
}

// Delete the batch transient.
delete_transient( 'option_optimizer_batch' );

// Delete the plugin option.
delete_option( 'option_optimizer' );