Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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:

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>';
}

}

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

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>';

}
share|improve this answer
    
Brilliant thank you!!! I did have to follow @vancoder's advice and remove the pre tags to make it work :) –  sta777 Apr 12 '13 at 8:33
add comment

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.

share|improve this answer
    
Thank you muchly!!! I had to remove the pre tags from @Rajeev Vyas's answer in order for it to work :) –  sta777 Apr 12 '13 at 8:34
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.