Skip to content

Instantly share code, notes, and snippets.

@bookchiq
Created September 11, 2025 23:56
Show Gist options
  • Select an option

  • Save bookchiq/176d92adef09d5905dc35e7166f39f04 to your computer and use it in GitHub Desktop.

Select an option

Save bookchiq/176d92adef09d5905dc35e7166f39f04 to your computer and use it in GitHub Desktop.
Generate a CSV of legacy URLs or IDs with their updated permalinks
<?php
// Register admin page for exporting legacy URLs.
add_action( 'admin_init', 'handle_legacy_url_export' );
/**
* Handle the legacy URL export request.
*/
function handle_legacy_url_export() {
// Handle legacy URLs export request.
if (
isset( $_GET['action'] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'export-legacy-urls' === $_GET['action'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
) {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'You do not have sufficient permissions to access this page.' );
}
export_legacy_urls_to_csv();
exit;
}
// Handle legacy IDs export request.
if (
isset( $_GET['action'] ) && // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'export-legacy-ids' === $_GET['action'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
) {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'You do not have sufficient permissions to access this page.' );
}
export_legacy_ids_to_csv();
exit;
}
}
/**
* Generate and return a CSV file with legacy URLs and permalinks.
*/
function export_legacy_urls_to_csv() {
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=legacy-urls.csv' );
$output = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
fputcsv( $output, array( 'Legacy URL', 'New Permalink' ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
$args = array(
'post_type' => 'any',
'posts_per_page' => -1,
'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- this is key to the function.
array(
'key' => '_legacy_url',
'compare' => 'EXISTS',
),
),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$legacy_url = get_post_meta( get_the_ID(), '_legacy_url', true );
if ( empty( $legacy_url ) ) {
continue;
}
$permalink = get_permalink();
fputcsv( $output, array( $legacy_url, $permalink ) );
}
wp_reset_postdata();
}
fclose( $output ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
exit;
}
/**
* Generate and return a CSV file with legacy IDs and current permalinks.
*/
function export_legacy_ids_to_csv() {
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=legacy-ids.csv' );
$output = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
fputcsv( $output, array( 'Legacy ID', 'Current Permalink' ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
$args = array(
'post_type' => 'any',
'posts_per_page' => -1,
'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- this is key to the function.
array(
'key' => '_legacy_id',
'compare' => 'EXISTS',
),
),
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$legacy_id = get_post_meta( get_the_ID(), '_legacy_id', true );
if ( empty( $legacy_id ) ) {
continue;
}
$permalink = get_permalink();
fputcsv( $output, array( $legacy_id, $permalink ) );
}
wp_reset_postdata();
}
fclose( $output ); // phpcs:ignore WordPress.WP.AlternativeFunctions -- we are streaming output, not writing to a filesystem file.
exit;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment