CSV Looper Provider - ID vs File Name Problems

Hi Charlie,

I have hit a problem, which I hope you may be able to resolve. If memory serves me right, the CSV looper provider used to require the file’s URL. In the meanwhile, you are using the link, which gets the file’s URL.

I have a specific scenario, which causes big issues. We have a volunteer rota, which is managed by an ever-updating CSV. The process is as follows:

  • Looper provider is liked to the originally uploaded CSV (e.g. https://www.domain.com/wp-contents/uploads/myfile.csv). This file feeds the looper.
  • The CSV is updated, the old CSV is deleted.
  • The new CSV is uploaded - as the old version has been deleted, it is still given the the same file name and URL. However, its ID is different!

In the pre-file-picker version of the CSV looper provider, this was not a problem - it is now, as the looper provider looks for the ID, not the filename.

Do you have any ideas how we can get around this?

Thanks,
Christopher

I don’t know how you are replacing the file, but if you use this plugin it’ll keep the same attachment ID I believe.

You can also try using the External API’s CSV type and just point the URL to your own site.

Let me know if that helps.

Simply file delete in media library and new version uploaded - it keeps the same file name upon upload, but obviously a different ID.

I will check the two links! Thanks.

Charlie,

Thanks for the pointer to the plugin! It has led me to a lighter-weight alternative via functions.php, which works (something for a future release?)

/**
 * Lightweight Media File Replacement
 * Works in both Grid and List views
 */

// Add "Replace File" link to List View
add_filter('media_row_actions', 'cww_add_replace_media_link', 10, 2);
function cww_add_replace_media_link($actions, $post) {
    $actions['replace_file'] = '<a href="' . admin_url('upload.php?page=cww-replace-media&attachment_id=' . $post->ID) . '">Replace File</a>';
    return $actions;
}

// Add "Replace File" button to Grid View and Edit Media modal
add_filter('attachment_fields_to_edit', 'cww_add_replace_field_to_modal', 10, 2);
function cww_add_replace_field_to_modal($form_fields, $post) {
    $replace_url = admin_url('upload.php?page=cww-replace-media&attachment_id=' . $post->ID);
    
    $form_fields['replace_file'] = array(
        'label' => 'Replace File',
        'input' => 'html',
        'html' => '<a href="' . esc_url($replace_url) . '" class="button button-secondary">Replace This File</a>',
        'helps' => 'Upload a new file to replace this one whilst keeping the same ID and URL'
    );
    
    return $form_fields;
}

// Register admin page for replacement
add_action('admin_menu', 'cww_register_replace_media_page');
function cww_register_replace_media_page() {
    add_submenu_page(
        null, // Hidden from menu
        'Replace Media File',
        'Replace Media',
        'upload_files',
        'cww-replace-media',
        'cww_replace_media_page'
    );
}

// Replacement page UI
function cww_replace_media_page() {
    if (!current_user_can('upload_files')) {
        wp_die('Unauthorised');
    }
    
    $attachment_id = isset($_GET['attachment_id']) ? intval($_GET['attachment_id']) : 0;
    
    if (!$attachment_id) {
        wp_die('Invalid attachment ID');
    }
    
    $attachment = get_post($attachment_id);
    $file_path = get_attached_file($attachment_id);
    $file_url = wp_get_attachment_url($attachment_id);
    
    ?>
    <div class="wrap">
        <h1>Replace Media File</h1>
        <p><strong>Current file:</strong> <?php echo esc_html(basename($file_path)); ?></p>
        <p><strong>URL:</strong> <code><?php echo esc_html($file_url); ?></code></p>
        
        <form method="post" enctype="multipart/form-data">
            <?php wp_nonce_field('cww_replace_media', 'cww_replace_nonce'); ?>
            <input type="hidden" name="attachment_id" value="<?php echo esc_attr($attachment_id); ?>">
            
            <p>
                <label for="replacement_file"><strong>Choose replacement file:</strong></label><br>
                <input type="file" name="replacement_file" id="replacement_file" required>
            </p>
            
            <p>
                <label>
                    <input type="checkbox" name="keep_filename" value="1" checked>
                    Keep original filename (preserves URL and all references)
                </label>
            </p>
            
            <?php submit_button('Replace File'); ?>
        </form>
    </div>
    <?php
}

// Handle file replacement
add_action('admin_init', 'cww_handle_replace_media');
function cww_handle_replace_media() {
    if (!isset($_POST['cww_replace_nonce']) || !wp_verify_nonce($_POST['cww_replace_nonce'], 'cww_replace_media')) {
        return;
    }
    
    if (!current_user_can('upload_files')) {
        wp_die('Unauthorised');
    }
    
    $attachment_id = intval($_POST['attachment_id']);
    $keep_filename = isset($_POST['keep_filename']);
    
    if (empty($_FILES['replacement_file']['tmp_name'])) {
        wp_die('No file uploaded');
    }
    
    $old_file_path = get_attached_file($attachment_id);
    
    // Determine new filename
    if ($keep_filename) {
        $new_filename = basename($old_file_path);
    } else {
        $new_filename = sanitize_file_name($_FILES['replacement_file']['name']);
    }
    
    $new_file_path = dirname($old_file_path) . '/' . $new_filename;
    
    // Delete old file
    if (file_exists($old_file_path)) {
        @unlink($old_file_path);
    }
    
    // Move uploaded file to correct location
    if (!move_uploaded_file($_FILES['replacement_file']['tmp_name'], $new_file_path)) {
        wp_die('Failed to replace file');
    }
    
    // Update attachment metadata
    $filetype = wp_check_filetype($new_file_path);
    wp_update_post([
        'ID' => $attachment_id,
        'post_mime_type' => $filetype['type'],
    ]);
    
    // Update attached file path
    update_attached_file($attachment_id, $new_file_path);
    
    // Regenerate metadata for images
    if (wp_attachment_is_image($attachment_id)) {
        wp_generate_attachment_metadata($attachment_id, $new_file_path);
    }
    
    // Clear caches
    clean_post_cache($attachment_id);
    
    wp_redirect(admin_url('upload.php?replaced=1'));
    exit;
}

// Success notice
add_action('admin_notices', 'cww_replace_media_notice');
function cww_replace_media_notice() {
    if (isset($_GET['replaced'])) {
        echo '<div class="notice notice-success is-dismissible"><p>File replaced successfully!</p></div>';
    }
}

Many thanks for such a quick response. So much appreciated!
Christopher