Headers already sent error with CSV export plugin

I have built a WordPress plugin that allows the user to export all pages, with their levels and urls, to a csv file.

The problem I have is that I keep getting error messages when trying to export the csv file:

Read More

Warning: Cannot modify header information – headers already sent

I have checked the config & functions files for spaces, as well as trying on different installations, but still can’t get this to work!!!

Does anybody know how to fix this please?

Plugin code:

/*
Plugin Name: Your Site's Functionality Plugin
Description: All of the important functionality of your site belongs in this.
Version: 0.1
License: GPL
Author: Your Name
Author URI: yoururl
*/
add_action('admin_menu', 'my_page_export_menu');

function my_page_export_menu() {
   add_submenu_page('edit-pages.php', __("Wordpress Export Pages to CSV", "my-page-export"), __("Export Page List", "my_page_export_menu"), 'edit_pages', __FILE__,'my_page_export_menu_options');
}

function my_page_export_menu_options() {

echo '<div id="treecontrol" style="margin:20px 0;position:relative;">
    <form method="post" id="download_form" action=""><input type="submit" name="download_csv" class="button-primary" value="Export" /></form>
</div>';

if ( isset($_POST['download_csv']) ) {

    $text = wp_list_pages("echo=0&title_li=");
    $html = preg_replace('/class=".*?"/', '', $text);
    $html = strip_tags($html, '<ul>, <li>, <a>');
    $html = '<ul>'.$html.'</ul>';

    function get_depth(DOMElement $element)
    {
        $depth = -1;
        while (
            $element->parentNode->tagName === 'li' || 
            $element->parentNode->tagName === 'ul'
        ) {
            if ($element->parentNode->tagName === 'ul') {
                $depth++;
            }
            $element = $element->parentNode;
        }
        return $depth;
    }

    $dom = new DOMDocument;
    $dom->preserveWhiteSpace = false;
    $dom->loadHTML($html);
    echo '<pre>';
    $fp = fopen("php://output", "w");

    $file = 'test_export';
    $filename = $file."_".date("Y-m-d_H-i",time());
    header("Content-type: text/csv");
    header("Content-disposition: csv" . date("Y-m-d") . ".csv");
    header( "Content-disposition: filename=".$filename.".csv");
    header("Pragma: no-cache");
    header("Expires: 0");

    foreach ($dom->getElementsByTagName('a') as $li) {
     printf(
          '%s%s%s', 
          str_repeat(',', get_depth($li)),
          trim($li->childNodes->item(0)->nodeValue),
          ',,,,=HYPERLINK("'.$li->getAttribute( 'href' ).'")'.PHP_EOL
      );
    }           
    echo '</pre>';

} else {
    echo '<ul>';
    wp_list_pages("&title_li=");
    echo '</ul>';
}

}

Related posts

Leave a Reply

2 comments

  1. Move your download/output code into admin_init hook. This hook is called before anything is output. It should work.

    <?php 
    /*
    Plugin Name: Your Site's Functionality Plugin
    Description: All of the important functionality of your site belongs in this.
    Version: 0.1
    License: GPL
    Author: Your Name
    Author URI: yoururl
    */
    add_action('admin_menu', 'my_page_export_menu');
    
    add_action('admin_init','wpse9876_download_csv');
    function my_page_export_menu() {
       add_submenu_page('edit-pages.php', __("Wordpress Export Pages to CSV", "my-page-export"), __("Export Page List", "my_page_export_menu"), 'edit_pages', __FILE__,'my_page_export_menu_options');
    }
    
    
    function wpse9876_download_csv(){
    
        if ( isset($_POST['download_csv']) ) {
    
            $text = wp_list_pages("echo=0&title_li=");
            $html = preg_replace('/class=".*?"/', '', $text);
            $html = strip_tags($html, '<ul>, <li>, <a>');
            $html = '<ul>'.$html.'</ul>';
    
            function get_depth(DOMElement $element)
            {
                $depth = -1;
                while (
                        $element->parentNode->tagName === 'li' ||
                        $element->parentNode->tagName === 'ul'
                ) {
                    if ($element->parentNode->tagName === 'ul') {
                        $depth++;
                    }
                    $element = $element->parentNode;
                }
                return $depth;
            }
    
            $dom = new DOMDocument;
            $dom->preserveWhiteSpace = false;
            $dom->loadHTML($html);
            echo '<pre>';
            $fp = fopen("php://output", "w");
    
            $file = 'test_export';
            $filename = $file."_".date("Y-m-d_H-i",time());
            header("Content-type: text/csv");
            header("Content-disposition: csv" . date("Y-m-d") . ".csv");
            header( "Content-disposition: filename=".$filename.".csv");
            header("Pragma: no-cache");
            header("Expires: 0");
    
            foreach ($dom->getElementsByTagName('a') as $li) {
                printf(
                        '%s%s%s',
                        str_repeat(',', get_depth($li)),
                        trim($li->childNodes->item(0)->nodeValue),
                        ',,,,=HYPERLINK("'.$li->getAttribute( 'href' ).'")'.PHP_EOL
                );
            }
            echo '</pre>';
            exit;
        }
    }
    
    function my_page_export_menu_options() {
    
    echo '<div id="treecontrol" style="margin:20px 0;position:relative;">
        <form method="post" id="download_form" action=""><input type="submit" name="download_csv" class="button-primary" value="Export" /></form>
    </div>';
    
    echo '<ul>';
    wp_list_pages("&title_li=");
    echo '</ul>';
    
    }
    
  2. You have

    echo '<pre>';
    

    right before you set your headers. That will break it.

    Also, you didn’t show the entire “Cannot modify…” error message. It should include directions to the exact line of code causing the issue.