Last active
August 9, 2024 10:16
-
-
Save rmpel/78a710f2d0c3cabffab7cace0b438944 to your computer and use it in GitHub Desktop.
ACF FieldGroups Deduplication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Sometimes, shit happens and you end up with duplication of ACF FieldGroups. | |
* This mu-plugin will fix that. | |
* It is also compatible with ACF-to-PHP. | |
*/ | |
add_action( 'admin_init', 'deduplicate_acf_data' ); | |
function deduplicate_acf_data() { | |
if ( empty( $_SERVER ) && 'cli' !== php_sapi_name() ) { | |
// not CLI and not a web request, bail. | |
return; | |
} | |
if ( ! current_user_can( 'manage_options' ) ) { | |
return; | |
} | |
if ( $_SERVER['REQUEST_METHOD'] !== 'GET' ) { | |
return; | |
} | |
if ( ! is_admin() ) { | |
return; | |
} | |
if ( ( $_GET['acf-deduplicated'] ?? 0 ) > 2 ) { | |
wp_die( 'ACF deduplication is stuck in a loop.' ); | |
} | |
global $wpdb; | |
$acf_groups = $wpdb->get_results( "SELECT ID, post_title, post_name FROM {$wpdb->prefix}posts WHERE post_type = 'acf-field-group' ORDER BY ID" ); | |
$acf_groups_unique = $wpdb->get_col( "SELECT DISTINCT(post_name) FROM {$wpdb->prefix}posts WHERE post_type = 'acf-field-group'" ); | |
// Check for duplication. | |
if ( count( $acf_groups ) === count( $acf_groups_unique ) ) { | |
return; | |
} | |
// Disable ACF to PHP sync temporarily. | |
add_filter( 'pre_option_acf_to_php_enable_sync', '__return_null' ); | |
// There is duplication. | |
// Find all IDs of the duplicated ACF groups, except the first one found. | |
$duplicated_ids = []; | |
foreach ( $acf_groups as $acf_group ) { | |
if ( in_array( $acf_group->post_name, $acf_groups_unique, true ) && ! array_key_exists( $acf_group->post_name, $duplicated_ids ) ) { | |
// This is the first occurrence of this ACF group, we create the empty list, we continue thereby skipping this first record. | |
$duplicated_ids[ $acf_group->post_name ] = []; | |
} else { | |
// This is a duplicate. | |
$duplicated_ids[ $acf_group->post_name ][] = $acf_group->ID; | |
} | |
} | |
// With duplicated field-groups, come duplicated fields. | |
// We will just delete the duplicated fields, and trigger an ACF refresh by reducing the "last_modified" field of the ACF field-group. | |
foreach ( $duplicated_ids as $acf_group_name => $acf_group_ids ) { | |
// We will keep the first ACF field-group, and delete the rest. | |
foreach ( $acf_group_ids as $acf_group_id_to_delete ) { | |
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}posts WHERE post_type = 'acf-field-group' AND ID = %d", $acf_group_id_to_delete ) ); | |
} | |
// Trigger an ACF refresh by reducing the "last_modified" field of the ACF field-group. | |
$wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}posts SET post_modified = post_modified - 1, post_modified_gmt = post_modified_gmt - 1 WHERE post_name = %s", $acf_group_name ) ); | |
} | |
// Cleanup acf-fields. | |
$orphan_post_ids = $wpdb->get_col( "SELECT ID FROM wp_posts WHERE post_parent NOT IN (SELECT ID FROM wp_posts WHERE post_type = 'acf-field-group') AND post_type = 'acf-field'" ); | |
foreach ( $orphan_post_ids as $orphan_post_id ) { | |
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}posts WHERE ID = %d", $orphan_post_id ) ); | |
} | |
// reload the page. | |
$deduplicated_count = $_GET['acf-deduplicated'] ?? 0; | |
$deduplicated_count++; | |
wp_redirect( add_query_arg( 'acf-deduplicated', $deduplicated_count, $_SERVER['REQUEST_URI'] ) ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment