$links The plugin action links. * @param string $file The plugin file. * * @return array */ public function filter_plugin_actions( $links, $file ): array { /* Static so we don't call plugin_basename on every plugin row. */ static $this_plugin; if ( ! $this_plugin ) { $this_plugin = \plugin_basename( AAA_OPTION_OPTIMIZER_FILE ); } if ( $file === $this_plugin ) { $settings_link = '' . \__( 'Optimize Options', 'aaa-option-optimizer' ) . ''; // Put our link before other links. \array_unshift( $links, $settings_link ); } return $links; } /** * Adds the admin page under the Tools menu. * * @return void */ public function add_admin_page() { \add_management_page( __( 'AAA Option Optimizer', 'aaa-option-optimizer' ), __( 'Option Optimizer', 'aaa-option-optimizer' ), 'manage_options', 'aaa-option-optimizer', [ $this, 'render_admin_page_ajax' ] ); } /** * Enqueue our scripts. * * @param string $hook The current page hook. * * @return void */ public function enqueue_scripts( $hook ) { if ( $hook !== 'tools_page_aaa-option-optimizer' ) { return; } \wp_enqueue_style( 'aaa-option-optimizer', plugin_dir_url( AAA_OPTION_OPTIMIZER_FILE ) . 'css/style.css', [], '2.0.1' ); \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.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', 'datatables' ], // Dependencies. filemtime( plugin_dir_path( AAA_OPTION_OPTIMIZER_FILE ) . 'js/admin-script.js' ), // Version. true // In footer. ); \wp_localize_script( 'aaa-option-optimizer-admin-js', 'aaaOptionOptimizer', [ 'root' => esc_url_raw( rest_url() ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'i18n' => [ 'filterBySource' => esc_html__( 'Filter by source', 'aaa-option-optimizer' ), 'showValue' => esc_html__( 'Show', 'aaa-option-optimizer' ), 'addAutoload' => esc_html__( 'Add autoload', 'aaa-option-optimizer' ), 'removeAutoload' => esc_html__( 'Remove autoload', 'aaa-option-optimizer' ), 'deleteOption' => esc_html__( 'Delete', 'aaa-option-optimizer' ), 'createOptionFalse' => esc_html__( 'Create option with value false', 'aaa-option-optimizer' ), 'noAutoloadedButNotUsed' => esc_html__( 'All autoloaded options are in use.', 'aaa-option-optimizer' ), 'noUsedButNotAutoloaded' => esc_html__( 'All options that are used are autoloaded.', 'aaa-option-optimizer' ), 'noOptionsSelected' => esc_html__( 'No options selected.', 'aaa-option-optimizer' ), 'bulkActions' => esc_html__( 'Bulk actions', 'aaa-option-optimizer' ), 'noBulkActionSelected' => esc_html__( 'No action selected.', 'aaa-option-optimizer' ), 'delete' => esc_html__( 'Delete', 'aaa-option-optimizer' ), 'apply' => esc_html__( 'Apply', 'aaa-option-optimizer' ), 'search' => esc_html__( 'Search:', 'aaa-option-optimizer' ), 'entries' => [ '_' => \esc_html__( 'entries', 'aaa-option-optimizer' ), '1' => \esc_html__( 'entry', 'aaa-option-optimizer' ), ], 'sInfo' => sprintf( // translators: %1$s is the start, %2$s is the end, %3$s is the total, %4$s is the entries. esc_html__( 'Showing %1$s to %2$s of %3$s %4$s', 'aaa-option-optimizer' ), '_START_', '_END_', '_TOTAL_', '_ENTRIES-TOTAL_' ), 'sInfoEmpty' => esc_html__( 'Showing 0 to 0 of 0 entries', 'aaa-option-optimizer' ), 'sInfoFiltered' => sprintf( // translators: %1$s is the max, %2$s is the entries-max. esc_html__( '(filtered from %1$s total %2$s)', 'aaa-option-optimizer' ), '_MAX_', '_ENTRIES-MAX_' ), 'sZeroRecords' => esc_html__( 'No matching records found', 'aaa-option-optimizer' ), 'oAria' => [ 'orderable' => esc_html__( ': Activate to sort', 'aaa-option-optimizer' ), 'orderableReverse' => esc_html__( ': Activate to invert sorting', 'aaa-option-optimizer' ), 'orderableRemove' => esc_html__( ': Activate to remove sorting', 'aaa-option-optimizer' ), 'paginate' => [ 'first' => esc_html__( 'First', 'aaa-option-optimizer' ), 'last' => esc_html__( 'Last', 'aaa-option-optimizer' ), 'next' => esc_html__( 'Next', 'aaa-option-optimizer' ), 'previous' => esc_html__( 'Previous', 'aaa-option-optimizer' ), ], ], ], ] ); } /** * Render a table section. * * @param string $section The section (usually thead or tfoot). * @param string[] $columns The columns to render. * * @return void */ public function table_section( $section, $columns ) { echo '<' . esc_html( $section ) . '>'; echo ''; foreach ( $columns as $column ) { switch ( $column ) { case 'actions': echo '' . esc_html__( 'Actions', 'aaa-option-optimizer' ) . ''; break; case 'autoload': echo '' . esc_html__( 'Autoload', 'aaa-option-optimizer' ) . ''; break; case 'calls': echo '' . esc_html__( '# Calls', 'aaa-option-optimizer' ) . ''; break; case 'option': echo '' . esc_html__( 'Option', 'aaa-option-optimizer' ) . ''; break; case 'size': echo '' . esc_html__( 'Size (KB)', 'aaa-option-optimizer' ) . ''; break; case 'source': echo '' . esc_html__( 'Source', 'aaa-option-optimizer' ) . ''; break; case 'select-all': echo ''; break; } } echo ''; echo ''; } /** * Renders the admin page. * * @return void */ public function render_admin_page_ajax() { $option_optimizer = get_option( 'option_optimizer', [ 'used_options' => [] ] ); // Start HTML output. echo '

' . esc_html__( 'AAA Option Optimizer', 'aaa-option-optimizer' ) . '

'; global $wpdb; $autoload_values = \wp_autoload_values_to_autoload(); $placeholders = implode( ',', array_fill( 0, count( $autoload_values ), '%s' ) ); // phpcs:disable WordPress.DB $result = $wpdb->get_row( $wpdb->prepare( "SELECT count(*) AS count, SUM( LENGTH( option_value ) ) as autoload_size FROM {$wpdb->options} WHERE autoload IN ( $placeholders )", $autoload_values ) ); // phpcs:enable WordPress.DB echo '

' . esc_html__( 'Stats', 'aaa-option-optimizer' ) . '

'; echo '

' . 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'] ) ) ), 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 ) ) . '

'; echo '

' . esc_html__( 'Optimize', 'aaa-option-optimizer' ) . '

'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce is used for REST API. if ( isset( $_GET['tracking_reset'] ) && $_GET['tracking_reset'] === 'true' ) { echo '

' . esc_html__( 'Tracking data has been reset.', 'aaa-option-optimizer' ) . '

'; // Take the parameter out of the URL without reloading the page. echo ''; } echo '
'; echo '

' . esc_html__( 'We\'ve found the following things you can maybe optimize:', 'aaa-option-optimizer' ) . '

'; ?>
' . esc_html__( 'Unused, but autoloaded', 'aaa-option-optimizer' ) . ''; echo '

' . 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 ''; $this->table_section( 'thead', [ 'select-all', 'option', 'source', 'size', 'autoload', 'actions' ] ); ?> table_section( 'tfoot', [ 'select-all', 'option', 'source', 'size', 'autoload', 'actions' ] ); ?>

' . esc_html__( 'Used, but not autoloaded options', 'aaa-option-optimizer' ) . ''; echo '

' . 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 ''; $this->table_section( 'thead', [ 'select-all', 'option', 'source', 'size', 'autoload', 'calls', 'actions' ] ); ?> table_section( 'tfoot', [ 'select-all', 'option', 'source', 'size', 'autoload', 'calls', 'actions' ] ); ?>

' . esc_html__( 'Requested options that do not exist', 'aaa-option-optimizer' ) . ''; echo '

' . 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 ''; $this->table_section( 'thead', [ 'option', 'source', 'calls', 'actions' ] ); ?> table_section( 'tfoot', [ 'option', 'source', 'calls', 'actions' ] ); ?>

table_section( 'thead', [ 'select-all', 'option', 'source', 'size', 'autoload', 'actions' ] ); ?> table_section( 'tfoot', [ 'select-all', 'option', 'source', 'size', 'autoload', 'actions' ] ); ?>