#2810 - Ability To Configure Which Fields To Search For Duplications On#2882
Conversation
kodinkat
commented
Feb 5, 2026
- fixes: Ability to configure which fields to search for duplicates on. #2810
- Added checks for the existence of Foundation components before initializing the Accordion and MediaQuery functions to prevent potential errors in environments where Foundation is not loaded.
- Improved mobile filter collapse functionality by ensuring Foundation is available before executing related logic.
- Added functionality to configure fields for duplicate detection in the general settings tab.
- Introduced a new form for selecting fields to check for duplicates, ensuring the 'name' field is always included.
- Enhanced JavaScript to manage field selection and submission, utilizing a multi-select component for better user experience.
- Created helper functions to extract field values based on type for duplicate searches.
- Updated site options to store duplicate field configurations, allowing for flexible management of duplicate detection across post types.
- Enhanced the collapse_filters function in modular-list.js for better readability by formatting conditional checks.
- Updated contacts.js to ensure the merge duplicate modal is properly initialized before opening, adding error handling for missing Foundation components and modal instances.
- Enhanced the logic for processing duplicate fields configuration in the general settings tab, ensuring that user-defined settings are respected and defaults are applied when necessary.
- Improved JavaScript to handle form submissions for duplicate fields, including validation and sanitization of input data.
- Updated PHP to clear cache after saving settings, ensuring fresh data is read on subsequent requests.
- Streamlined the extraction of field values for duplicate searches, improving code readability and maintainability.
- Cleaned up whitespace and improved code readability in the duplicate fields configuration functions.
- Enhanced the logic for processing duplicate fields in the admin settings, ensuring proper validation and sanitization of input data.
- Streamlined the handling of default fields for duplicate detection across post types, maintaining user-defined settings while applying defaults where necessary.
- Updated comments for clarity and maintainability throughout the affected files.
…ndentation for better readability.
…ag indentation for enhanced readability.
…r clarity
- Removed redundant mention of the 'name' field in the instructions for configuring duplicate record checks, streamlining the user guidance.
|
@claude review? |
|
I'll analyze this and get back to you. |
|
Hey @kodinkat, Could you look into (or clarify) these 2?
In duplicates-merging.php, the endpoint now calls 2 remove Foundation defensive checks in modular-list.js and |
- Simplified conditional checks for Foundation MediaQuery in the collapse_filters function for better readability.
- Streamlined the initialization of the Foundation Accordion by removing redundant checks, ensuring it is always executed when filter_accordions are present.
- Enhanced the merge duplicate modal opening logic in contacts.js by directly calling the foundation method, improving code clarity and reducing error handling complexity.
…ools-theme into 2810-ability-to-configure-which-fields-to-search-for-duplications-on
- Updated the to remove an unnecessary parameter in the duplicate ID retrieval function for cleaner code.
- Initialized as an associative array in to ensure a consistent structure.
- Enhanced JavaScript in to ensure is always treated as an array, improving robustness and preventing potential errors.
@corsacca good spot re point (1); as this was changed in error. Latest updates pushed and review ready..... |
| 'available_languages' => dt_get_available_languages(), | ||
| 'site_options' => dt_get_option( 'dt_site_options' ), | ||
| 'contacts_field_settings' => DT_Posts::get_post_field_settings( 'contacts' ), | ||
| 'duplicate_fields' => $duplicate_fields_data, |
There was a problem hiding this comment.
@kodinkat the field_settings for all post types could be directly available under dtOptionAPI. Then it can be used by other settings
| // Check if valid config exists for this post type | ||
| let selectedFields; | ||
| if ( | ||
| duplicateFieldsConfig.hasOwnProperty(postType) && |
| * @param string $post_type The post type to get defaults for | ||
| * @return array Array of field keys to check for duplicates | ||
| */ | ||
| if ( !function_exists( 'dt_get_duplicate_fields_defaults' ) ) { |
| dt_theme_enqueue_script( 'web-components', 'dt-assets/build/components/index.js', array(), false ); | ||
| dt_theme_enqueue_style( 'web-components-css', 'dt-assets/build/css/light.min.css', array() ); | ||
|
|
||
| if ( isset( $_GET['tab'] ) && ( ( $_GET['tab'] === 'people-groups' ) || ( $_GET['tab'] === 'general' ) ) ) { |
There was a problem hiding this comment.
this page need to work on /wp-admin/admin.php?page=dt_options as well.
…ools-theme into 2810-ability-to-configure-which-fields-to-search-for-duplications-on
- Updated function to ensure consistent return of default fields for post types, improving clarity and maintainability.
- Modified to normalize active tab handling and expose post field settings for use in duplicate fields configuration.
- Enhanced JavaScript to safely handle duplicate fields configuration and ensure compatibility with shared post field settings, improving robustness of the admin interface.
Code ReviewThanks for implementing this feature - configurable duplicate detection fields is a valuable addition. Here are my findings: Bugs / Functional Gaps1. The scoring block in 2.
Architecture / Code Quality3. Form data processed inside
4.
5. In Minor Issues6. Missing translation wrapper $this->box( 'top', 'Duplicate Detection Fields' );The string 7. alert('Field selector not found');Using 8. Indefinite
9. No enforcement that Code comments note that 10. Unnecessary complexity in The switch cases for SummaryThe core concept is solid and the new
|
- Enhanced the duplicate fields comparison logic to support various field types, including text, communication channels, tags, and multi-select, improving accuracy in duplicate detection.
- Simplified the retrieval of duplicate fields configuration by directly reading from the database, ensuring a consistent structure and reducing complexity in form processing.
- Removed redundant cache clearing to optimize performance when displaying duplicate fields settings in the admin interface.
Updated Code ReviewReviewing the current state of the PR. Several issues from the earlier automated review appear to be addressed — scoring in Bug:
|
- Updated SQL query strings to use consistent single quotes for better readability and maintainability.
- Improved the handling of dynamic table names and conditions in the SQL queries for duplicate detection, ensuring clarity and reducing potential errors.
Code ReviewGood progress on this feature. Several issues flagged in prior reviews appear still unresolved in the current diff. Here is a consolidated review of what remains. Bug (High):
|
| Priority | Issue |
|---|---|
| High | Hardcoded 'contacts' in query_for_duplicate_searches_v2() name-field SQL |
| Medium | get_post_field_settings() called in inner loop (performance) |
| Medium | in_array() missing strict mode |
| Medium | esc_sql() for LIKE values — should use $wpdb->esc_like() first |
| Minor | Missing __() translation wrapper on 'Duplicate Detection Fields' |
| Minor | alert() in JS |
| Minor | Unbounded setTimeout polling |
The hardcoded 'contacts' bug and the esc_like() issue are the most important to address before merge.
- Improved the construction of SQL queries by ensuring consistent escaping of values, particularly for LIKE operations, to enhance security and prevent SQL injection vulnerabilities.
- Updated the handling of dynamic post types in SQL queries for better clarity and maintainability.
Code Review — PR #2882: Configurable Duplicate Detection FieldsGood feature addition overall. The refactoring of Bugs / Correctness1. Missing In // communication_channel block - missing post_type filter:
$all_sql .= '... FROM ' . $wpdb->posts . ' p
LEFT JOIN ... INNER JOIN ... as type ON ( ... AND type.meta_value = \'access\' )
WHERE ( ' . implode( ' OR ', $where_parts ) . ' )
AND p.ID != ' . (int) $post_id;
// ^^^ no "AND p.post_type = ..." here, unlike the other blocks2. Fuzzy matching on When Performance3. In foreach ( $fields as $field_key ) {
$sanitized_field_key = sanitize_key( $field_key );
$field_settings = DT_Posts::get_post_field_settings( $post_type ); // called N times!
if ( isset( $field_settings[$sanitized_field_key] ) ) { ...
4. Both 5. This line (in Code Quality6. Non-translatable string in $this->box( 'top', 'Duplicate Detection Fields' );The label should go through $this->box( 'top', __( 'Duplicate Detection Fields', 'disciple_tools' ) );7. JS: Polling instead of // Current approach — polling every 100ms indefinitely:
setTimeout(initializeDuplicateFields, 100);
// Better:
customElements.whenDefined('dt-multi-select').then(initializeDuplicateFields);The polling loop has no timeout/escape condition, so if the component fails to load it will poll forever. 8. JS: Nested Line 673 calls 9. JS: alert('Field selector not found');This is inconsistent with the rest of the admin UI. Consider using a visible inline error message or the existing admin notice pattern instead. Minor / PHPCS10. Missing semicolons before Several PHP statements in <?php esc_html_e( 'Select fields...', 'disciple_tools' ) ?>
// ^ missing ;PHPCS will flag these. Add Summary
The core logic for configurable fields is sound. Issues 1, 2, and 5 are the ones worth prioritizing before merge. |
|
@corsacca review ready.... |
Code Review — PR #2882 (updated round)Good progress on the fixes. Here's a focused review of what remains. Bugs Still Outstanding1. Missing post_type filter in V2 SQL for communication_channel (High) The communication_channel UNION block in query_for_duplicate_searches_v2() still lacks the post type filter that every other block has. This can return false-positive matches from other post types that happen to store a meta value under the same field key. The name and else (postmeta) blocks both include AND p.post_type = '...', but the communication_channel block only filters on type.meta_value = 'access' with no post type clause. Add AND p.post_type = esc_sql($post_type) before AND p.ID != in that block. 2. get_post_field_settings() called inside an inner loop (Medium) In process_duplicate_fields() (tab-general.php), DT_Posts::get_post_field_settings( $post_type ) is called on every iteration of the inner $fields loop. Move it above the inner foreach: 3. wp_cache_delete( 'alloptions', 'options' ) is too aggressive (Medium) Both wp_cache_delete calls in process_duplicate_fields() are unnecessary — update_option() already handles its own cache invalidation. The alloptions deletion forces WordPress to re-read all options from the database on the very next request, affecting every plugin and core function, not just dt_site_options. Remove both lines. 4. in_array() missing strict mode in POST validation (Minor) Change: if ( !in_array( $post_type, $post_types ) ) { Minor / Code Style5. Non-translatable string in box() call Change: $this->box( 'top', 'Duplicate Detection Fields' ); 6. Missing semicolons before closing PHP tags (PHPCS) Multiple statements in display_duplicate_fields_settings() are missing ; before the closing ?> tag, e.g. esc_html_e( '...', 'disciple_tools' ) ?> should end with ; ?>. PHPCS will flag these. 7. JS: alert() for an internal error alert('Field selector not found') blocks the page. Use console.error() instead — consistent with how errors are surfaced elsewhere in the admin UI. 8. JS: Nested document.ready() is redundant The document.ready() at the bottom of the duplicate fields block is already inside the outer jQuery(document).ready() that wraps the entire dt-options.js file. The document is already ready at that point — call initializeDuplicateFields() directly instead. 9. JS: Unbounded setTimeout polling initializeDuplicateFields() will loop indefinitely if the web component never loads. Use the standard platform API instead: customElements.whenDefined('dt-multi-select').then(initializeDuplicateFields); What's Fixed
Summary
Issue 1 is the main one to address before merge. |
PR #2882 Review — Configurable Duplicate Detection FieldsThis is a well-structured feature addition. The previous review's highest-priority issues appear to have been addressed. Here's the current state: Fixed Since Previous Review ✅
Still Present / New Issues1. (Medium) In foreach ( $fields as $field_key ) {
$sanitized_field_key = sanitize_key( $field_key );
$field_settings = DT_Posts::get_post_field_settings( $post_type ); // <-- called N times per post typeMove this outside the inner loop (but inside the outer loop) to call it once per post type. 2. (Medium) The v2 SQL queries all include 3. (Low) Missing translation wrapper $this->box( 'top', 'Duplicate Detection Fields' );Per project conventions, user-facing strings must use 4. (Low) alert('Field selector not found');Using 5. (Low) Indefinite
customElements.whenDefined('dt-multi-select').then(() => {
updateFieldSelector(selectedPostType);
});6. (Low) Saving an empty field selection is silently ignored In if ( !empty( $sanitized_fields ) ) {
$duplicates_config[$post_type] = array_unique( $sanitized_fields );
}If a user deliberately clears all fields for a post type and saves, the config for that post type is not updated — the old value persists. The behavior is inconsistent with the intent; the UI should either prevent saving an empty selection (e.g., require at least one field) or save the empty array so the backend falls back to defaults as documented. SummaryThe core refactor is clean and the test coverage is comprehensive. The two items worth fixing before merging are the contacts-specific JOIN leaking into all post types in |

