avatar Gnat Dec 23. 2009. 1:39 pm
Hello,
I'm wondering if it is possible to get the entire output of another controller/action from a different one.

In the frameworks I'm used to I can call getPresentationFor('controller','method') and get the full html it would have output to the browser as a result. I need this for a module we're building.. Is that possible?
avatar Ilija Studen Staff Dec 24. 2009. 3:50 am
Sorry, this functionality is not built into activeCollab.
avatar Gnat Dec 28. 2009. 3:12 pm
So here's how I managed to do it....

I created a function print_pdf() and print_estimate() in my controller. They use a common layout. From print_pdf() I've done the following. You can see it calls the print_estimate function which triggers all the necessary smarty code paths etc. Then you can see $pdf = $this->renderOutput(); Which I've defined locally within my controller, which is basically your renderLayout() however I've swaped the tpl_display for tpl_fetch(). this allows me to output any page to pdf using wkhtmltopdf (webkit gui-less browser). It supports CSS and all that, and is MUCH much less time consuming than building a pdf by scratch via the various PDF php classes out there. Build the template in html and out comes styled pdfs.

    function print_pdf()
    {
        $this->print_estimate();

        $file = '/tmp/TNDG-ESTIMATE-'.$this->active_estimate->getId().'.html'; //tempnam('/tmp','estimate_');
        if(is_file($file))
            unlink($file);

        $pdf_file = '/tmp/TNDG-ESTIMATE-'.$this->active_estimate->getId().'.pdf';
        if(is_file($pdf_file))
            unlink($pdf_file);

        $pdf = $this->renderOutput();

        file_put_contents($file,$pdf);

        if (ob_get_contents())
            die('Some data has already been output, can\'t send PDF file');

        if (headers_sent())
            die('Some data has already been output to browser, can\'t send PDF file');

        header('Content-Description: File Transfer');
        header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
        header('Pragma: public');
        header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
        header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
        // force download dialog
        header('Content-Type: application/force-download');
        header('Content-Type: application/octet-stream', false);
        header('Content-Type: application/download', false);
        header('Content-Type: application/pdf', false);
        // use the Content-Disposition header to supply a recommended filename
        header('Content-Disposition: attachment; filename="'.basename($pdf_file).'";');
        header('Content-Transfer-Encoding: binary');

        exec("/usr/local/bin/wkhtmltopdf $file $pdf_file");

        $fsize = filesize($pdf_file);

        header('Content-Length: '.$fsize);

        echo file_get_contents($fsize);

        die();
    } // print_pdf
avatar Ilija Studen Staff Dec 28. 2009. 9:09 pm
Maybe you could also "catch" HTML that renderLayout() prints in output buffer. This does not require any new methods to be added to the controller - everything goes into action.
avatar Gnat Dec 28. 2009. 9:44 pm
I tried using the ob_get_contents stuff but the display just outputs straight to the browser so I couldn't get around it.