0

I am currently working on a custom extension to provide server-side LESS compiling (beyond what the current offerings are) for Magento 1x installs. I have the extension 99% done with the exception of the minifier. Here is my code to minify:

            if ($minify == 1) {
            // minify the css file list
            $temp = "";
            $cssFileContent = array();
            foreach ($cssFileList as $cssFile) {
                $temp .= file_get_contents($cssFile);
                $temp = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $temp);
                $temp = str_replace(': ', ':', $temp);
                $temp = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $temp);
                ob_start("ob_gzhandler");
                header("Content-type: text/css");
                $cssFileContent[] = array('filename' => $cssFile, 'content' => $temp);
                fclose($cssFile);
            }
            foreach ($cssFileContent as $fileContent) {
                fopen($fileContent['filename'], 'wb');
                fwrite($fileContent['filename'], $fileContent['content']);
                fclose($fileContent)['filename'];
            }
        }

This is being executed by an observer using a helper function. $CssFileList contains a list of CSS file names. As you can see, I am getting the contents and running some minification replaces and saving the filename and content data to an array. I then run a second foreach, open each file, attempt to write the content, and then close. (I had this entire action as one foreach initially, but while debugging the issue I am having I split them into two separate loops.)

The issue I am having is with fopen and fwrite. Per PHP documentation, fopen should open the file. If it isn't there, it creates it. Using the 'w' option truncates the data, and I use 'b' because I am on a Windows machine (using XAMPP).

If I run the code above as-is, it finds the files and truncates them (0 bytes). That's it. I thought maybe something was up with fwrite not working, so since fwrite cannot create a file itself, I tested it by manually deleting a file in $CssFileList and then commenting out fopen. fwrite() works flawlessly and minifies the code for the file as expected.

Why are fopen() and fwrite() not working together in this loop? I also tried to use the file_put_contents() method and instead of truncating and then adding the current loop iteration's content, it is actually adding the content from the last loop iteration along with the current content. (This makes the last file huge because it has all the content from the files before it.)

Help?

1
  • 4
    W'd like to close, not really related to magento.
    – sv3n
    Commented Oct 29, 2018 at 21:12

1 Answer 1

0

Is the code you posted accurate? This is not correct:

foreach ($cssFileContent as $fileContent) {
    fopen($fileContent['filename'], 'wb');
    fwrite($fileContent['filename'], $fileContent['content']);
    fclose($fileContent)['filename'];
}

fopen() takes a file name and returns a resource handle. Both fwrite() and fclose() take the resource handle as the first parameter - not the file name.

Your code should be:

foreach ($cssFileContent as $fileContent) {
    $handle = fopen($fileContent['filename'], 'wb');
    fwrite($handle, $fileContent['content']);
    fclose($handle);
}

(There was also an error with the way you invoked the fclose() function, but I assume that was a copy-paste error of some sort.)

Note that file_put_contents() does not append by default, it overwrites. It only appends if the FILE_APPEND flag is specified.

What you're seeing is a side effect of your other loop:

$temp .= file_get_contents($cssFile);

That appends each file's content to $temp, which means that each file will have the contents of all of the files before it. You probably want to just get rid of the period, resulting in:

// grab the contents, but don't append them to the previous contents
$temp = file_get_contents($cssFile);

Also note that you don't need the fclose($cssFile); in the first loop. file_get_contents() opens, reads, and closes the file, and fclose() expects an open handle as the first parameter (not a file name).

3
  • The fact that I was using the file name instead of the resource handle made this work, Agop. Thank you. Any idea why instead of truncating and then adding the current loop iteration's content, it is actually adding the content from the last loop iteration along with the current content. (This makes the last file huge because it has all the content from the files before it.) Basically, it is doing the same thing as file_put_contents(), which makes sense since it is a shorthand fopen(), fwrite() and fclose(). Commented May 6, 2015 at 16:57
  • I edited my answer to cover that as well.
    – Agop
    Commented May 6, 2015 at 17:04
  • Amazing answer, Agop. Thank you very, very much! Commented May 6, 2015 at 17:05

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