// ===== DEDUPE por videoId (dry-run seguro) ===== // Uso (só ADMIN): // Dry-run: /wp-admin/?obh_dedupe=1 // Executar: /wp-admin/?obh_dedupe=1&do=1 add_action('admin_init', function(){ if (!current_user_can('manage_options')) return; if (empty($_GET['obh_dedupe'])) return; $do = !empty($_GET['do']); @set_time_limit(0); // Pega todos os stations que tenham meta videoId $q = new WP_Query([ 'post_type' => 'station', 'post_status' => ['publish','draft','private','pending'], 'posts_per_page' => -1, 'meta_key' => 'videoId', 'fields' => 'ids', ]); $by_vid = []; foreach ($q->posts as $pid){ $vid = get_post_meta($pid, 'videoId', true); if (!$vid) continue; $by_vid[$vid][] = $pid; } $total_groups = 0; $affected = 0; $trashed = 0; $log = []; foreach ($by_vid as $vid => $ids){ if (count($ids) < 2) continue; // sem duplicata $total_groups++; // Separa por parent: filhos (playlist/álbum) NÃO serão tocados $root = []; $children = []; foreach ($ids as $id){ $p = get_post($id); if (!$p) continue; if ((int)$p->post_parent === 0) $root[] = $id; else $children[] = $id; } if (count($root) < 2) { // nada para limpar entre os "soltos" $log[] = "videoId $vid: ok (root=".count($root).", children=".count($children).")"; continue; } // Escolhe um canônico entre os "soltos": // 1) preferir meta type=single; 2) senão, o mais antigo $canonical = null; $fallback_id = null; $fallback_date = null; foreach ($root as $id){ $type = get_post_meta($id, 'type', true); $p = get_post($id); if (!$fallback_id || strtotime($p->post_date) < $fallback_date){ $fallback_id = $id; $fallback_date = strtotime($p->post_date); } if ($type === 'single' && !$canonical){ $canonical = $id; } } if (!$canonical) $canonical = $fallback_id; // Os demais "soltos" vão para lixeira (se for execução) $remove = array_diff($root, [$canonical]); if (!empty($remove)){ $affected++; if ($do){ foreach ($remove as $rid){ wp_trash_post($rid); $trashed++; } $log[] = "videoId $vid: mantido #$canonical; removidos (root) ".implode(',', $remove); } else { $log[] = "DRY-RUN videoId $vid: manter #$canonical; remover (root) ".implode(',', $remove); } } else { $log[] = "videoId $vid: ok (nenhum extra root)"; } } header('Content-Type: text/plain; charset=utf-8'); echo ($do ? "EXECUÇÃO\n" : "DRY-RUN (simulação)\n"); echo "Grupos com duplicatas: $total_groups\n"; echo "Grupos com limpeza (root): $affected\n"; if ($do) echo "Posts enviados à lixeira: $trashed\n"; echo "----- LOG -----\n"; foreach ($log as $l) echo $l."\n"; exit; }); Explorar – OnBeat

Explorar