2

I'm using this php code to cache css files into a middle own CMS.

<?php
ob_start("ob_gzhandler");
ob_start("compress");
header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$off = 3600;
$exp = "Expires: " . gmdate("D, d M Y H:i:s", time() + $off) . " GMT";
header($exp);

function compress($buffer) {
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer); // remove comments
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer); // remove tabs, spaces, newlines, etc.
    return $buffer;
}

require_once('style1.css');
require_once('style2.css');

?>

The big limitation in this code is that I cannot pass an argument to my "compress" function. For example, if I have a css file into an other directory, the relative path of the images are not replaced.

Do you know a way to add a parameter when i call my compress function and use for example something like this?

$buffer = str_replace('url("', 'url("'.$directory, $buffer);

Any suggestions are really appreciated!


Edit -> the final solution

After @Jack suggestions I'm arrived to this source.

Usage: in the header of the html page add this line: <link href="cacheCSS.php" rel="stylesheet" type="text/css" />

ob_start("ob_gzhandler");

class CWD {  
    private $path;

    public function __construct($path=NULL){
        if(!isset($path)) $path = '';
        $this->setPath($path);
    }

    public function setPath($path){
        $this->path = $path;
    }

    public function getPath() {
        return $this->path;
    }
}

$directory = new CWD();
$compress = function($buffer) use ($directory) {
    $buffer = str_replace('url("', 'url("'.$directory->getPath(), $buffer);
    $buffer = str_replace('url(\'', 'url(\''.$directory->getPath(), $buffer);
    $buffer = preg_replace('#^\s*//.+$#m', "", $buffer);
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
    return $buffer;
};

ob_start($compress);

header("Content-type: text/css; charset: UTF-8");
header("Cache-Control: must-revalidate");
$off = 0; # Set to a reaonable value later, say 3600 (1 hr);
$exp = "Expires: " . gmdate("D, d M Y H:i:s", time() + $off) . " GMT";
header($exp);

/* List of CSS files*/
$directory->setPath('path1/');
include('path1/style1.css');

ob_flush();
$directory->setPath('path2/');
include('path2/style2.css');

ob_flush();
$directory->setPath('path3/');
include('path3/style3.css');
Danilo
  • 2,016
  • 4
  • 24
  • 49

1 Answers1

3

Since PHP 5.3 you can use closures to accomplish this:

$directory = 'whatever';

$compress = function($buffer) use ($directory) {
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer); // remove comments
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer); // remove tabs, spaces, newlines, etc.

    $buffer = str_replace('url("', 'url("'.$directory, $buffer);

    return $buffer;
}

ob_start($compress);

Update

If your directory can change, you might want to use an object instead:

class CWD
{
    private $path;

    public function __construct($path)
    {
        $this->setPath($path);
    }

    public function setPath($path)
    {
        $this->path = $path;
    }

    public function getPath()
    {
        return $this->path;
    }
}

$directory = new CWD('/path/to/directory');

$compress = function($buffer) use ($directory) {
    // ...
    $buffer = str_replace('url("', 'url("'.$directory->getPath(), $buffer);
};

Then somewhere inside your code you would have:

$directory->setPath();
echo "whatever css";
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • It could be a good hint, but the path directory is not fixed and depends on the require directive. For example: require_once('dir1/style.css'); --> $directory = 'dir1/'; require_once('dir2/style.css'); --> $directory = 'dir2/'; Thank you to the patience. – Danilo Feb 13 '13 at 11:28
  • If the paths are to remain fixed for each file you can specify them above the include. $directory='dir1/'; require_once('dir1/style1.css'); and then change "use ($directory)" to "use (&$directory)" to pass the variable in by reference. – Levi Feb 13 '13 at 14:06
  • @Danilo If it changes, you can make it an object instead. – Ja͢ck Feb 13 '13 at 14:14
  • Edited the question. With the @Jack solution the result is still wrong.. :( – Danilo Feb 16 '13 at 16:56
  • 1
    @danilo you may have to try flushing the buffer before changing the directory. – Ja͢ck Feb 17 '13 at 04:45