Skip to content
Merged
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
72 changes: 58 additions & 14 deletions js/admin-script.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,33 @@ jQuery( document ).ready( function () {
return 'option_' + optionName.replace( /\./g, '_' );
}

/**
* Store sources (plugin names) for each table from AJAX responses.
*
* @type {Object}
*/
const tableSources = {};

/**
* Creates a column filter setup function bound to a specific table selector.
*
* @param {string} tableSelector - The table selector.
* @return {Function} The filter setup function.
*/
function createColumnFilterSetup( tableSelector ) {
return function () {
setupColumnFilters.call( this, tableSelector );
};
}

/**
* Initializes the DataTable for the given selector.
*
* @param {string} selector - The table selector.
*/
function initializeDataTable( selector ) {
const filterSetup = createColumnFilterSetup( selector );

const options = {
pageLength: 25,
autoWidth: false,
Expand All @@ -54,7 +75,7 @@ jQuery( document ).ready( function () {
return generateRowId( data.name );
},
initComplete() {
this.api().columns( 'source:name' ).every( setupColumnFilters );
this.api().columns( 'source:name' ).every( filterSetup );
},
language: aaaOptionOptimizer.i18n,
};
Expand All @@ -66,7 +87,10 @@ jQuery( document ).ready( function () {
'aaa-option-optimizer/v1/unused-options',
headers: { 'X-WP-Nonce': aaaOptionOptimizer.nonce },
type: 'GET',
dataSrc: 'data',
dataSrc( json ) {
tableSources[ selector ] = json.sources || [];
return json.data;
},
};
options.serverSide = true;
options.processing = true;
Expand All @@ -75,7 +99,7 @@ jQuery( document ).ready( function () {
};
options.initComplete = function () {
getBulkActionsForm( selector, [ 'autoload-off' ] ).call( this );
this.api().columns( 'source:name' ).every( setupColumnFilters );
this.api().columns( 'source:name' ).every( filterSetup );
};
options.order = [ [ 1, 'asc' ] ]; // Order by 2nd column, first column is checkbox.
}
Expand All @@ -87,7 +111,10 @@ jQuery( document ).ready( function () {
'aaa-option-optimizer/v1/used-not-autoloaded-options',
headers: { 'X-WP-Nonce': aaaOptionOptimizer.nonce },
type: 'GET',
dataSrc: 'data',
dataSrc( json ) {
tableSources[ selector ] = json.sources || [];
return json.data;
},
};
options.serverSide = true;
options.processing = true;
Expand All @@ -96,7 +123,7 @@ jQuery( document ).ready( function () {
};
options.initComplete = function () {
getBulkActionsForm( selector, [ 'autoload-on' ] ).call( this );
this.api().columns( 'source:name' ).every( setupColumnFilters );
this.api().columns( 'source:name' ).every( filterSetup );
};
options.order = [ [ 1, 'asc' ] ]; // Order by 2nd column, first column is checkbox.
}
Expand All @@ -106,10 +133,16 @@ jQuery( document ).ready( function () {
url: `${ aaaOptionOptimizer.root }aaa-option-optimizer/v1/options-that-do-not-exist`,
headers: { 'X-WP-Nonce': aaaOptionOptimizer.nonce },
type: 'GET',
dataSrc: 'data',
dataSrc( json ) {
tableSources[ selector ] = json.sources || [];
return json.data;
},
};
options.serverSide = true;
options.processing = true;
options.initComplete = function () {
this.api().columns( 'source:name' ).every( filterSetup );
};
}

if ( selector === '#all_options_table' ) {
Expand All @@ -124,7 +157,7 @@ jQuery( document ).ready( function () {
'autoload-on',
'autoload-off',
] ).call( this );
this.api().columns( 'source:name' ).every( setupColumnFilters );
this.api().columns( 'source:name' ).every( filterSetup );
};
options.order = [ [ 1, 'asc' ] ]; // Order by 2nd column, first column is checkbox.
}
Expand Down Expand Up @@ -253,8 +286,10 @@ jQuery( document ).ready( function () {

/**
* Sets up the column filters for the DataTable.
*
* @param {string} tableSelector - The table selector to get sources from.
*/
function setupColumnFilters() {
function setupColumnFilters( tableSelector ) {
const column = this;
const select = document.createElement( 'select' );
select.add(
Expand All @@ -266,13 +301,22 @@ jQuery( document ).ready( function () {
column.search( select.value, { exact: true } ).draw();
} );

column
.data()
.unique()
.sort()
.each( function ( d ) {
select.add( new Option( d ) );
// Use sources from AJAX response if available (for server-side processing),
// otherwise fall back to column data (for client-side processing).
const sources = tableSources[ tableSelector ];
if ( sources && sources.length > 0 ) {
sources.forEach( function ( source ) {
select.add( new Option( source ) );
} );
} else {
column
.data()
.unique()
.sort()
.each( function ( d ) {
select.add( new Option( d ) );
} );
}
}

/**
Expand Down
78 changes: 57 additions & 21 deletions src/class-rest.php
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ public function get_unused_options() {
$autoload_option_keys = array_fill_keys( $autoloaded_option_names, true );
$unused_keys = array_diff_key( $autoload_option_keys, $used_options );

// Collect all unique sources (plugin names) before any filtering.
$all_sources = [];
foreach ( array_keys( $unused_keys ) as $option_name ) {
$plugin_name = $this->get_plugin_name( $option_name );
$all_sources[ $plugin_name ] = true;
}
$all_sources = array_keys( $all_sources );
sort( $all_sources );

// Apply source filter to unused keys if specified.
$filter_by_source = isset( $_GET['columns'][2]['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['columns'][2]['search']['value'] ) ) ) : '';
if ( '' !== $filter_by_source ) {
Expand Down Expand Up @@ -315,6 +324,7 @@ public function get_unused_options() {
'recordsTotal' => $total_unused,
'recordsFiltered' => $total_unused,
'data' => $response_data,
'sources' => $all_sources,
],
200
);
Expand Down Expand Up @@ -366,6 +376,15 @@ public function get_used_not_autoloaded_options() {
// Find used options that are not autoloaded.
$non_autoloaded_used_keys = array_diff_key( $used_options, $autoload_option_keys );

// Collect all unique sources (plugin names) before any filtering.
$all_sources = [];
foreach ( array_keys( $non_autoloaded_used_keys ) as $option_name ) {
$plugin_name = $this->get_plugin_name( $option_name );
$all_sources[ $plugin_name ] = true;
}
$all_sources = array_keys( $all_sources );
sort( $all_sources );

// Filter by source (plugin).
$filter_by_source = isset( $_GET['columns'][2]['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['columns'][2]['search']['value'] ) ) ) : '';
if ( '' !== $filter_by_source ) {
Expand All @@ -391,6 +410,7 @@ function ( $option_name ) use ( $search ) {
'recordsTotal' => 0,
'recordsFiltered' => 0,
'data' => [],
'sources' => $all_sources,
],
200
);
Expand Down Expand Up @@ -442,6 +462,7 @@ function ( $option_name ) use ( $search ) {
'recordsTotal' => $total_filtered,
'recordsFiltered' => $total_filtered,
'data' => $response_data,
'sources' => $all_sources,
],
200
);
Expand Down Expand Up @@ -490,31 +511,14 @@ public function get_options_that_do_not_exist() {
// Get used options that are not autoloaded.
$non_autoloaded_keys = array_diff_key( $used_options, $autoload_option_keys );

// Filter by source (plugin).
$filter_by_source = isset( $_GET['columns'][1]['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['columns'][1]['search']['value'] ) ) ) : '';
if ( '' !== $filter_by_source ) {
$non_autoloaded_keys = $this->filter_by_source( $non_autoloaded_keys, $filter_by_source );
}

// Search.
$search = isset( $_GET['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['search']['value'] ) ) ) : '';
if ( '' !== $search ) {
$non_autoloaded_keys = array_filter(
$non_autoloaded_keys,
function ( $option_name ) use ( $search ) {
return stripos( $option_name, $search ) !== false;
},
ARRAY_FILTER_USE_KEY
);
}

if ( empty( $non_autoloaded_keys ) ) {
return new \WP_REST_Response(
[
'draw' => intval( $_GET['draw'] ?? 0 ),
'recordsTotal' => 0,
'recordsFiltered' => 0,
'data' => [],
'sources' => [],
],
200
);
Expand All @@ -532,11 +536,11 @@ function ( $option_name ) use ( $search ) {
);
$existing_keys = array_fill_keys( $existing_option_names, true );

// Filter only those that do NOT exist.
$response_data = [];
// Build array of non-existing options (before any filtering).
$non_existing_options = [];
foreach ( $non_autoloaded_keys as $option => $count ) {
if ( ! isset( $existing_keys[ $option ] ) ) {
$response_data[] = [
$non_existing_options[ $option ] = [
'name' => $option,
'plugin' => $this->get_plugin_name( $option ),
'count' => $count,
Expand All @@ -545,6 +549,37 @@ function ( $option_name ) use ( $search ) {
}
}

// Collect all unique sources (plugin names) before any filtering.
$all_sources = [];
foreach ( $non_existing_options as $row ) {
$all_sources[ $row['plugin'] ] = true;
}
$all_sources = array_keys( $all_sources );
sort( $all_sources );

// Filter by source (plugin).
$filter_by_source = isset( $_GET['columns'][1]['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['columns'][1]['search']['value'] ) ) ) : '';
if ( '' !== $filter_by_source ) {
$non_existing_options = array_filter(
$non_existing_options,
function ( $row ) use ( $filter_by_source ) {
return false !== stripos( $row['plugin'], $filter_by_source );
}
);
}

// Search.
$search = isset( $_GET['search']['value'] ) ? trim( \sanitize_text_field( \wp_unslash( $_GET['search']['value'] ) ) ) : '';
if ( '' !== $search ) {
$non_existing_options = array_filter(
$non_existing_options,
function ( $row ) use ( $search ) {
return stripos( $row['name'], $search ) !== false;
}
);
}

$response_data = array_values( $non_existing_options );
$total_filtered = count( $response_data );

// Pagination.
Expand All @@ -564,6 +599,7 @@ function ( $option_name ) use ( $search ) {
'recordsTotal' => $total_filtered,
'recordsFiltered' => $total_filtered,
'data' => $response_data,
'sources' => $all_sources,
],
200
);
Expand Down