Skip to content

Commit

Permalink
Massive improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
jdevalk committed Mar 1, 2024
1 parent 025ef43 commit d90b895
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 22 deletions.
39 changes: 39 additions & 0 deletions js/admin-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,46 @@

jQuery( document ).ready(
function ($) {
if ( $( '#unused_options_table' ).length ) {
let table = new DataTable( '#unused_options_table', { columns: [ null, { searchable: false }, { searchable: false }, { searchable: false } ] } );
}
if ( $( '#used_not_autloaded_table' ).length ) {
let table = new DataTable( '#used_not_autloaded_table', { columns: [ null, { searchable: false }, { searchable: false }, { searchable: false }, { searchable: false } ] } );
}
if ( $( '#requested_do_not_exist_table' ).length ) {
let table = new DataTable( '#requested_do_not_exist_table', { columns: [ null, { searchable: false }, { searchable: false } ] } );
}

// Handle the "Remove Autoload" button click.
$( '.add-autoload' ).on(
'click',
function (e) {
e.preventDefault();
var optionName = $( this ).data( 'option' );

var requestData = {
'autoload': 'yes'
};

$.ajax(
{
url: aaaOptionOptimizer.root + 'aaa-option-optimizer/v1/update-autoload/' + optionName,
method: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader( 'X-WP-Nonce', aaaOptionOptimizer.nonce );
},
data: requestData,
success: function (response) {
$( 'tr#option_' + optionName ).remove();
},
error: function (response) {
alert( 'Failed to add autoload for ' + optionName );
}
}
);
}
);

$( '.remove-autoload' ).on(
'click',
function (e) {
Expand Down
1 change: 1 addition & 0 deletions js/vendor/dataTables.dataTables.min.css

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions js/vendor/dataTables.min.js

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<!-- Exclude the Coverage output directory. -->
<exclude-pattern>/coverage/*</exclude-pattern>

<exclude-pattern>/js/vendor/*</exclude-pattern>

<!-- Exclude minified Javascript files. -->
<exclude-pattern>*.min.js</exclude-pattern>

Expand Down Expand Up @@ -72,13 +74,10 @@
For more information, also see:
https://github.com/PHPCompatibility/PHPCompatibility
-->
<!--
<config name="testVersion" value="5.6-"/>
<config name="testVersion" value="7.4-"/>
<rule ref="PHPCompatibilityWP">
<include-pattern>*\.php</include-pattern>
</rule>
-->


<!--
#############################################################################
Expand Down
177 changes: 166 additions & 11 deletions src/class-admin-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function register_hooks() {
public function add_admin_page() {
add_management_page(
__( 'AAA Option Optimizer', 'aaa-option-optimizer' ),
__( 'AAA Option Optimizer', 'aaa-option-optimizer' ),
__( 'Option Optimizer', 'aaa-option-optimizer' ),
'manage_options',
'aaa-option-optimizer',
[ $this, 'render_admin_page' ]
Expand All @@ -36,10 +36,25 @@ public function add_admin_page() {
* Enqueue our scripts.
*/
public function enqueue_scripts() {
wp_enqueue_script(
'datatables',
plugin_dir_url( AAA_OPTION_OPTIMIZER_FILE ) . 'js/vendor/dataTables.min.js',
[], // Dependencies.
'2.0.1',
true // In footer.
);

wp_enqueue_style(
'datatables',
plugin_dir_url( AAA_OPTION_OPTIMIZER_FILE ) . 'js/vendor/dataTables.dataTables.min.css',
[],
'2.0.1'
);

wp_enqueue_script(
'aaa-option-optimizer-admin-js',
plugin_dir_url( AAA_OPTION_OPTIMIZER_FILE ) . 'js/admin-script.js',
[ 'jquery' ], // Dependencies.
[ 'jquery', 'datatables' ], // Dependencies.
filemtime( plugin_dir_path( AAA_OPTION_OPTIMIZER_FILE ) . 'js/admin-script.js' ), // Version.
true // In footer.
);
Expand All @@ -54,6 +69,38 @@ public function enqueue_scripts() {
);
}

/**
* Get the length of a value.
*
* @param mixed $value The input value.
*
* @return string
*/
private function get_length( $value ) {
if ( is_array( $value ) ) {
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- intended here.
$length = strlen( serialize( $value ) );
} else {
$length = strlen( $value );
}
return number_format( ( $length / 1024 ), 2 );
}

/**
* Print a value.
*
* @param mixed $value The input value.
*
* @return string
*/
private function print_value( $value ) {
if ( is_array( $value ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r -- intended here.
return '<code>' . print_r( $value, 1 ) . '</code>';
}
return '<code>' . esc_html( $value ) . '</code>';
}

/**
* Renders the admin page.
*/
Expand All @@ -69,50 +116,158 @@ function ( $value, $key ) {
ARRAY_FILTER_USE_BOTH
);

$unused_options = array_diff( array_keys( $autoload_options ), $option_optimizer['used_options'] );
$unused_options = [];
$non_autoloaded_options = [];

// Get the autoloaded options that aren't used.
foreach ( $autoload_options as $option => $value ) {
if ( isset( $option_optimizer['used_options'][ $option ] ) ) {
continue;
}
$unused_options[ $option ] = $value;
}

// Determine the options that _are_ used, but not auto-loaded.
foreach ( $option_optimizer['used_options'] as $option => $count ) {
if ( isset( $autoload_options[ $option ] ) ) {
continue;
}
$non_autoloaded_options[ $option ] = $count;
}

// Some of the options that are used but not auto-loaded, may not exist.
if ( ! empty( $non_autoloaded_options ) ) {
$options_that_do_not_exist = [];
$non_autoloaded_options_full = [];
foreach ( $non_autoloaded_options as $option => $count ) {
$value = get_option( $option, 'aaa-no-return-value' );
if ( $value === 'aaa-no-return-value' ) {
$options_that_do_not_exist[ $option ] = $count;
continue;
}
$non_autoloaded_options_full[ $option ] = [
'count' => $count,
'value' => $value,
];
}
}

// Start HTML output.
echo '<style>
.aaa_option_table td, .aaa_option_table th { padding: 5px 10px; text-align: left; }
.aaa_option_table tr:hover { background-color: white; }
.aaa_option_table { margin-left: -5px; border-spacing: 0; }
.aaa_option_table td, .aaa_option_table th { padding: 5px 10px 5px 5px; text-align: left; width: 25%; }
.aaa_option_table tr:nth-child(even) { background-color: #fff; }
.aaa_option_table tr:hover { background-color: #ddd; }
.aaa_option_table td.value code { display:block; max-width: 200px; height: 20px; overflow: hidden; }
div.dt-container .dt-input { padding: 5px 20px 5px 10px !important; max-width: none !important; }
</style>';
echo '<div class="wrap"><h1>' . esc_html__( 'AAA Option Optimizer', 'aaa-option-optimizer' ) . '</h1>';

global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$result = $wpdb->get_row( "SELECT count(*) AS count, SUM(LENGTH(option_value)) as autoload_size FROM {$wpdb->options} WHERE autoload='yes'" );

echo '<h2>' . esc_html__( 'Stats', 'aaa-option-optimizer' ) . '</h2>';
echo '<p>' .
sprintf(
// translators: %1$s is the date, %2$s is the number of options at stat, %3$s is the size at start in KB, %4$s is the number of options now, %5$s is the size in KB now.
esc_html__( 'When you started on %1$s you had %2$s autoloaded options, for %3$sKB of memory. Now you have %4$s options, for %5$sKB of memory.', 'aaa-option-optimizer' ),
esc_html( gmdate( 'Y-m-d', strtotime( $option_optimizer['starting_point_date'] ) ) ),
esc_html( $option_optimizer['starting_point_num'] ),
isset( $option_optimizer['starting_point_num'] ) ? esc_html( $option_optimizer['starting_point_num'] ) : '-',
number_format( ( $option_optimizer['starting_point_kb'] ), 1 ),
esc_html( $result->count ),
number_format( ( $result->autoload_size / 1024 ), 1 )
) . '</p>';

// Render differences.
echo '<h2>' . esc_html__( 'Unused Autoloaded Options', 'aaa-option-optimizer' ) . '</h2>';
echo '<p>' . esc_html__( 'We\'ve found the following things you can maybe optimize:', 'aaa-option-optimizer' ) . '</p>';
echo '<ul>';
echo '<li><a href="#unused-autoloaded">' . esc_html__( 'Unused Autoloaded Options', 'aaa-option-optimizer' ) . '</a></li>';
if ( ! empty( $non_autoloaded_options ) ) {
echo '<li><a href="#used-not-autoloaded">' . esc_html__( 'Used But Not Autoloaded Options', 'aaa-option-optimizer' ) . '</a></li>';
}
if ( ! empty( $options_that_do_not_exist ) ) {
echo '<li><a href="#requested-do-not-exist">' . esc_html__( 'Requested Options That Do Not Exist', 'aaa-option-optimizer' ) . '</a></li>';
}
echo '</ul>';
// Render differences.
echo '<h2 id="unused-autoloaded">' . esc_html__( 'Unused Autoloaded Options', 'aaa-option-optimizer' ) . '</h2>';
if ( ! empty( $unused_options ) ) {
echo '<table class="aaa_option_table">';
echo '<p>' . esc_html__( 'The following options are autoloaded on each pageload, but AAA Option Optimizer has not been able to detect them being used.', 'aaa-option-optimizer' );
echo '<table id="unused_options_table" class="aaa_option_table display compact">';
echo '<thead>';
echo '<tr>';
echo '<th>' . esc_html__( 'Option', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Size', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Value', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Actions', 'aaa-option-optimizer' ) . '</th>';
echo '</tr>';
foreach ( $unused_options as $option ) {
echo '</thead>';
echo '<tbody>';
foreach ( $unused_options as $option => $value ) {
echo '<tr id="option_' . esc_attr( str_replace( ':', '', str_replace( '.', '', $option ) ) ) . '"><td>' . esc_html( $option ) . '</td>';
echo '<td>' . number_format( ( strlen( $autoload_options[ $option ] ) / 1024 ), 2 ) . 'KB</td>';
echo '<td>' . esc_html( $this->get_length( $value ) ) . 'KB</td>';
echo '<td class="value">' . esc_html( $this->print_value( $value ) ) . '</td>';
echo '<td><button class="button remove-autoload" data-option="' . esc_attr( $option ) . '">' . esc_html__( 'Remove Autoload', 'aaa-option-optimizer' ) . '</button> ';
echo ' <button class="button delete-option" data-option="' . esc_attr( $option ) . '">' . esc_html__( 'Delete Option', 'aaa-option-optimizer' ) . '</button></td></tr>';
}
echo '</tbody>';
echo '</table>';
} else {
echo '<p>' . esc_html__( 'All autoloaded options are in use.', 'aaa-option-optimizer' ) . '</p>';
}

// Render differences.
if ( ! empty( $non_autoloaded_options ) ) {
echo '<h2 id="used-not-autoloaded">' . esc_html__( 'Used But Not Autoloaded Options', 'aaa-option-optimizer' ) . '</h2>';
echo '<p>' . esc_html__( 'The following options are *not* autoloaded on each pageload, but AAA Option Optimizer has detected that they are being used. If one of the options below has been called a lot and is not very big, you might consider adding autoload to that option.', 'aaa-option-optimizer' );
echo '<table id="used_not_autloaded_table" class="aaa_option_table">';
echo '<thead>';
echo '<tr>';
echo '<th>' . esc_html__( 'Option', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Size', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Value', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( '# Calls', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Actions', 'aaa-option-optimizer' ) . '</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
foreach ( $non_autoloaded_options_full as $option => $arr ) {
echo '<tr id="option_' . esc_attr( str_replace( ':', '', str_replace( '.', '', $option ) ) ) . '">';
echo '<td>' . esc_html( $option ) . '</td>';
echo '<td>' . esc_html( $this->get_length( $arr['value'] ) ) . 'KB</td>';
echo '<td class="value">' . esc_html( $this->print_value( $arr['value'] ) ) . '</td>';
echo '<td>' . esc_html( $arr['count'] ) . '</td>';
echo '<td><button class="button add-autoload" data-option="' . esc_attr( $option ) . '">' . esc_html__( 'Add Autoload', 'aaa-option-optimizer' ) . '</button> ';
}
echo '</tbody>';
echo '</table>';
} else {
echo '<p>' . esc_html__( 'All options that are used are autoloaded.', 'aaa-option-optimizer' ) . '</p>';
}

if ( ! empty( $options_that_do_not_exist ) ) {
echo '<h2 id="requested-do-not-exist">' . esc_html__( 'Requested Options That Do Not Exist', 'aaa-option-optimizer' ) . '</h2>';
echo '<p>' . esc_html__( 'The following options are requested sometimes, but AAA Option Optimizer has detected that they do not exist. If one of the options below has been called a lot, it might help to create it with a value of false.', 'aaa-option-optimizer' );
echo '<table id="requested_do_not_exist_table" class="aaa_option_table">';
echo '<thead>';
echo '<tr>';
echo '<th>' . esc_html__( 'Option', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( '# Calls', 'aaa-option-optimizer' ) . '</th>';
echo '<th>' . esc_html__( 'Actions', 'aaa-option-optimizer' ) . '</th>';
echo '</tr>';
echo '</thead>';
echo '<tbody>';
foreach ( $options_that_do_not_exist as $option => $count ) {
echo '<tr id="option_' . esc_attr( str_replace( ':', '', str_replace( '.', '', $option ) ) ) . '">';
echo '<td>' . esc_html( $option ) . '</td>';
echo '<td>' . esc_html( $count ) . '</td>';
echo '<td><button class="button add-autoload" data-option="' . esc_attr( $option ) . '">' . esc_html__( 'Create Option with value false', 'aaa-option-optimizer' ) . '</button> ';
}
echo '</tbody>';
echo '</table>';
}

echo '</div>'; // Close .wrap.
}
}
16 changes: 11 additions & 5 deletions src/class-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Plugin {
* Registers hooks.
*/
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.
add_filter( 'all', [ $this, 'monitor_option_accesses' ] );

Expand Down Expand Up @@ -62,21 +64,25 @@ public function monitor_option_accesses( $tag ) {
*/
protected function add_option_usage( $option_name ) {
// Check if this option hasn't been tracked yet and add it to the array.
if ( ! in_array( $option_name, $this->accessed_options, true ) ) {
$this->accessed_options[] = $option_name;
if ( ! array_key_exists( $option_name, $this->accessed_options ) ) {
$this->accessed_options[ $option_name ] = 1;
return;
}
++$this->accessed_options[ $option_name ];
}

/**
* Update the 'option_optimizer' option with the list of used options at the end of the page load.
*/
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' => [] ] );

// Merge the newly accessed options with the existing ones, avoiding duplicates.
$updated_used_options = array_unique( array_merge( $option_optimizer['used_options'], $this->accessed_options ) );
$option_optimizer['used_options'] = $updated_used_options;
$option_optimizer['used_options'] = $this->accessed_options;

// Update the 'option_optimizer' option with the new list.
update_option( 'option_optimizer', $option_optimizer, true );
Expand Down
13 changes: 11 additions & 2 deletions src/class-rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,23 @@ public function register_rest_routes() {
*/
public function update_option_autoload( $request ) {
$option_name = $request['option_name'];
$autoload = $request['autoload'] === 'yes' ? 'yes' : 'no';
$autoload = $request['autoload'];
$option_value = get_option( $option_name );

if ( ! in_array( $autoload, [ 'yes', 'no' ], true ) ) {
return new \WP_Error( 'invalid_autoload_value', 'Invalid autoload value', [ 'status' => 400 ] );
}

if ( false === $option_value ) {
return new \WP_Error( 'option_not_found', 'Option does not exist', [ 'status' => 404 ] );
}

update_option( $option_name, $option_value, $autoload );
delete_option( $option_name );
$succeeded = add_option( $option_name, $option_value, '', $autoload );

if ( ! $succeeded ) {
return new \WP_Error( 'update_failed', 'Updating the option failed', [ 'status' => 400 ] );
}
return new \WP_REST_Response( [ 'success' => true ], 200 );
}

Expand Down

0 comments on commit d90b895

Please sign in to comment.