Question

Smarty Templating for php lets your write output filters that are called everytime fetch() or display() is called. Smarty also uses output buffers and you can't create your own (you can't have an output buffer while the other one is still active).

My question is, I want to run tidy on the entire document after it is done, rather than in pieces as it displays templates. I can't rewrite the software I'm using to the degree that would make it use display or fetch only once, but I still need to use the output filter/tidy before the output is flushed in smarty, on the entire document at once. But I see no way inherent in smarty to do this.

The code I have works fine:

function tidy_html(&$output, &$smarty){
     $config = array(
           'indent'         => true,
           #'output-html'   => true,
           'wrap'           => 0,
           'drop-proprietary-attributes'    =>    false,
           'indent-cdata' => true,
           'indent-spaces' => 5,
           'tab-size' => 5,
           'show-warnings' => true
         #'markup' => false ,
         #'sort-attributes' => 'alpha',
         #'char-encoding' => 'utf8'
    );
    try {
        $tidy = new tidy;
        $tidy->parseString($output, $config, 'utf8');
        $tidy->cleanRepair();

    } catch (Exception $e) {
        $tidy = $output;
    }
    return $tidy;
}


$view->register_outputfilter('tidy_html');

However because it runs on pieces as fetch() or display() are called, if the closing brackets for say, a table aren't present in that file it closes them for me and disrupts the layout, breaking my site. Most of it displays fine it only has issues closing tables and some div boxes early because of how this software is set up it puts the page into blocks and calls display on each block. If that block contains pieces of a table it closes them early resulting in layout breakage. At least I think that is what is going on any help would be appreciated. Maybe it's possible to grab the output buffer before it's flushed somehow even tho smarty is controlling it?

Was it helpful?

Solution

I turned on php tags in the templates and put this at the beginning of the file that is called on any request:

{php}
    ob_start('tidy_html_buffer');
{/php}

And this at the end of the file:

{php}
    ob_end_flush();
{/php}

And this is the callback function:

function tidy_html_buffer(&$output){
    $config = array(
        'indent'         => true,
        #'output-html'   => true,
        'wrap'           => 0,
        'drop-proprietary-attributes'    =>    false,
        'indent-cdata' => true,
        'indent-spaces' => 5,
        'tab-size' => 5,
        'show-warnings' => true
        #'markup' => false ,
        #'sort-attributes' => 'alpha',
        #'char-encoding' => 'utf8'
    );
    try {
        $tidy = new tidy;
        $tidy->parseString($output, $config, 'utf8');
        $tidy->cleanRepair();

    } catch (Exception $e) {
        if(!empty($e)) print_r($e);
        $tidy = $output;
    }
    #print_r($tidy);
    return $tidy;
}

Since gzip compression is on you can't get performance benefits from flushing early so this achieves the result with minimal overhead or performance hits especially after cached.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top