CSS minify with PHP extension - php

How can I minify a .php file with CSS contents?
Currently I get a 400 error.
Normally I call minify like this
<link rel="stylesheet" type="text/css"
href="{$workspace}/min/f=workspace/css/common.css" />
EDIT
The answer is changing the minify source code, but what is the change I should make?
In other words.. this call should work and process as CSS..
<link rel="stylesheet" type="text/css"
href="{$workspace}/min/f=workspace/css/common.php" />
Maybe with an optional declaration?
<link rel="stylesheet" type="text/css"
href="{$workspace}/min/f=workspace/css/common.php&type=css" />
EDIT
I created the project here # https://github.com/into/less-less

Your CSS+PHP script outputs CSS only after it's requested from a server and parsed by PHP. Minify reads files directly from the server, skipping the HTTP request. So I see two paths:
Less optimal [?]: make minify download the CSS like this:
<link rel="stylesheet" type="text/css" href="{$workspace}/min/f=http://site.com/workspace/css/common.php" />
Include Minify lib in your common.php file and use its classes (e.g. Minify_CSS) before output. Something like echo Minify_CSS::minify($css)
Update:
Your example repo contains a strange file name which wouldn't let me pull/push appropriately, so here's the changed report.php:
<pre>
<strong>LESS in</strong>
<?= file_get_contents('workspace/less/common.less') ?>
- - - - -
<strong>CSS out</strong>
<?
require 'workspace/php/lessc.inc.php';
$lc = new lessc();
$contents = file_get_contents( 'workspace/less/common.less' );
$css = $lc->parse( $contents );
echo $css;
?>
<strong>Minified</strong>
<?php
require 'workspace/min/lib/Minify/CSS/Compressor.php';
echo Minify_CSS_Compressor::process($css);
?>
</pre>

No, you can't easily do it as minify heavily depends on file extensions (css,js,?). For example it is used to determine what HTTP headers send to client(application/x-javascript,text/css,?), what minifier class to use, is this file safe to parse etc.
But I'm almost certain that this situation can be avoided. Could you please describe why exactly you want to do this?
If you insist on doing it this way I can propose a few dirty hacks to make it work, but it requires changing minify's source code so I don't really know if that is a good idea.
Upd:
There is no nice way to change this source: it has really bad structure. In minify v2.1.3 you can simply change the following:
Path: lib/Minify/Controller/Base.php##Minify_Controller_Base::_fileIsSafe()
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt'));
-->
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt', 'php'));
Path: lib/Minify/Controller/MinApp.php##Minify_Controller_MinApp::setupSources()
preg_match('/^[^,]+\\.(css|js)(?:,[^,]+\\.\\1)*$/', $_GET['f'])
-->
preg_match('/^[^,]+\\.(css|js|php)(?:,[^,]+\\.\\1)*$/', $_GET['f'])
Path: lib/Minify/##Minify_Source::__construct()
case 'css' : $this->contentType = 'text/css';
-->
case 'php': case 'css': $this->contentType = 'text/css';
and everything will work, but you must set $min_serveOptions['minApp']['allowDirs'] in configuration carefully as any user may be able to view any php file from this directories.

Using CSS Min, you are freely could do whatsoever and you could also "processing" your stlyesheet in php script, then minify it on the fly : its DEAD simple to do that, and guess what, it just A SINGLE FILE.
Another way is, dont use any PHP script to process or doing some logical at your css file, instead, you could have separated small css file then you just load whatever you want by building new cache file or just combine and output the link tag.
However, if you are now have something like this in your common.php (php file/script that outputing the css, yes?)
<?php
$style = '';
$bodyStyle = 'body {
background-color: #000;
margin: 40px;
font: 13px/20px normal Helvetica, Arial, sans-serif;
color: #fff;
}';
// I assumed you are about proccesing something here..
// ...
// Then you merged all style into one string, and output it as css file
$style = $bodyStyle + $otherStyle + $whateverStyle;
header('Content-Type: text/css');
echo $style;
?>
And you still want to make your app bloated and make your code more unreadable (wait, there still more...), also want to modify Minify class/lib to minify and cache you pseudo-css-php, then you need to "hacking" the source as follow :
lib/Minify/Controller/Base.php : 135, change to :
return in_array(strrev($revExt), array('js', 'css', 'html', 'txt', 'php'));
lib/Minify/Controller/MinApp.php : 75, change to :
! preg_match('/^[^,]+\\.(css|js|php)(?:,[^,]+\\.\\1)*$/', $_GET['f'])
lib/Minify/Source.php, change several things :
Add one variable as a PHP flag, in , after line 41 perhaps
/**
* #var bool
*/
public $isPHP = FALSE;
In same file, at line : 67, add a condition :
case 'php' : $this->isPHP = TRUE;
$this->contentType = 'text/css';
break;
Last, replace getContent() function, into :
public function getContent()
{
if($this->isPHP)
{
include($this->filepath);
}
else
{
$content = (null !== $this->filepath)
? file_get_contents($this->filepath)
: ((null !== $this->_content)
? $this->_content
: call_user_func($this->_getContentFunc, $this->_id)
);
}
// remove UTF-8 BOM if present
return (pack("CCC",0xef,0xbb,0xbf) === substr($content, 0, 3))
? substr($content, 3)
: $content;
}
You also need to change your common.php into Minify spec, so now, your common.php should looks like :
You need to put all your stylesheet as string and assign it into $content variable
<?php
//$style = '';
$bodyStyle = 'body {
background-color: #000;
margin: 40px;
font: 13px/20px normal Helvetica, Arial, sans-serif;
color: #fff;
}';
// I assumed you are about proccesing something here..
// ...
// Then you merged all style into one string, and output it as css file
// $style = $bodyStyle + $otherStyle + $whateverStyle;
// header('Content-Type: text/css');
// echo $style;
$content = $bodyStyle + $otherStyle + $whateverStyle;
?>

Yes, there is one and it works pretty well:
https://github.com/c9s/pecl-cssmin
The API is pretty simple:
<?php
echo cssmin("body { .... } .rule { } .rule2 { color: #fff; }");

Related

How to link something from manifest.json

I'm using Webpack with the CleanWebpackPlugin, but I use an index.php. So HtmlWebpackPlugin isn't an option. I found a different plugin called WebpackManifestPlugin. This creates a file with the files and their hash called manifest.json. It looks like this:
{
"main.js": "css.d915ef.js",
"main.css": "main.d915ef.css"
}
But how do I use this in my head?
<link rel="stylesheet" type="text/css" href="dist/main.css">
Because this doesn't work.
Use that function in php script
function asset($asset_name)
{
$manifest = file_get_contents("./manifest.json");
$manifest = json_decode($manifest, true); //decode json string to php associative array
if (!isset($manifest[$asset_name])) return $asset_name; //if manifest.json doesn't contain $asset_name then return $asset_name itself
return "/dist/" . $manifest[$asset_name];
}
It will read and parse manifest.json and replace "main.js" with "css.d915ef.js"
You can use asset() function while generating yout html, like this:
<link rel="stylesheet" type="text/css" href="<?php echo asset("main.js"); ?>">
Please, be aware, that file_get_contents("./manifest.json") will only work correctly if your php script and manifest.json is in the same folder. If not - you need to provide correct path to manifest.json here.
I have a similar situation with Create React App and a PHP file.
The Create React App configuration creates an asset-manifest.json file in which all the files that are needed in the page are listed under the entrypoints key.
"entrypoints": [
"static/js/runtime-main.bff00530.js",
"static/js/2.8bab6741.chunk.js",
"static/css/main.262e5e5f.chunk.css",
"static/js/main.e2f4dbf8.chunk.js"
]
In my code I'm doing the following (expanding on #krylov123's answer):
// get the original values
$manifest = file_get_contents("./asset-manifest.json");
$manifest_values = json_decode($manifest, true);
$entrypoints = $manifest_values['entrypoints'];
Then I'm creating two separate arrays: one for the css and another for the js files. In order to do so I've created an helper function filterPaths (you may create your own):
// return only paths continaint a specific string
function filterPaths($paths, $value): array {
return array_filter($paths, function ($filename) use ($value): bool {
return strpos($filename, $value) !== false;
});
}
Here I create the two arrays:
// filter '.css' files
$css_files = filterPaths($entrypoints, '/css/');
// filter '.js' files
$js_files = filterPaths($entrypoints, '/js/');
Then in the html part I loop over the two arrays in order to print link tags for CSS and script tags for JavaScript.
This is the syntax using blade, but you can adapt it to normal php:
#foreach($css_files as $link)
<link href="{{ $link }}" rel="stylesheet">
#endforeach
#foreach($js_files as $link)
<script src="{{ $link }}"></script>
#endforeach
Another option is to disable hash inserting via webpack.config.js file.
You need to find all [hash] occurence and remove it from webpack.config.js. Then use npm run to recompile everything.
For example, you have
output: {
path: path.resolve(__dirname, './public/'),
filename: '[name].[hash].js'
}
Replace it with:
output: {
path: path.resolve(__dirname, './public/'),
filename: '[name].js'
}

How to compile SCSS with scssphp

I'm currently trying to compile some SCSS which I'm receiving via a form request. The current workflow is that the user submits form data as follows:
{"$background_color":"#f3f3f3","$logo_url":"https:\/\/logo.co\/random"}
I then transform this input to the following:
$background_color: '#f3f3f3';
$logo_url: 'https://logo.co/random'
This should be valid for the purposes of compiling it to CSS so I run it through SCSSPHP with the following:
$scss->addImportPath(Storage::disk('tmp'));
$output = $scss->compile("#import 'test'; $statement ");
No errors are triggered when I run this and the output is:
#import 'test';
My test.scss is as follows:
$background_colour: 'red'
$logo_url: 'https://test.com'
.logo {
background-image: $logo_url;
}
.background_colour {
background-colour: $background_colour;
}
What am I doing wrong here?
The problem is that you're not passing a string to this function.
Parse your scss as a string by using the function file_get_contents
require_once "scssphp/scss.inc.php";
use Leafo\ScssPhp\Compiler;
$scss = new Compiler();
// Gets the content of the scss file in string format
$scss_string = file_get_contents(path/to/scss.file);
echo $scss->compile($scss_string);

How can I execute a PHP file before using its content with another file?

Situation
I’m mixing HTML & CSS with PHP variables, so that I can manage a lot of settings with just one config file. This is all working fine, but I’m trying to merge and minify the CSS now. And this causes a problem.
Problem
The variables won’t be echoed into the compressed sheet because the PHP script won't be executed. And that is because file_get_contents() converts the content into a string.
Question
Is it in some way possible to execute the files first, and then grab their contents? Or grab their contents in another way, a way that they still will be executed?
Files
config.php
$priColor = '#000';
base-stylesheet.php
/* CSS header defined */
/* config.php included */
body{
background-color: <?= $priColor ?>;
}
specific-stylesheet.php
/* CSS header defined */
/* config.php included */
.site-specific-element{
background-color: <?= $priColor ?>;
}
minified-stylesheets.php
// Set files that must be minified
$cssFiles = array(
"base-styleseet.php",
"specific-stylesheet.php"
);
// Get those files
$buffer = "";
foreach ($cssFiles as $cssFile) {
$buffer .= file_get_contents($cssFile);
}
// Minify and echo them
minifyCSS($buffer);
echo $buffer;
index.php
<link rel="stylesheet" href="minified-stylesheets.php">
I think what you need to do is include the file into a PHP buffer and then minify the buffer
// Set files that must be minified
$cssFiles = array(
"base-styleseet.php",
“specific-stylesheet.php"
);
// Get those files
ob_start();
foreach ($cssFiles as $cssFile) {
include($cssFile);
}
// Minify and echo them
$css = minifyCSS(ob_get_clean());
echo $css;
You already are familiar with the ob_start() method.
But I will show a better alternative (and faster):
Your main file:
$cssFiles = array(
"base-styleseet.php",
"specific-stylesheet.php"
);
$buffer = "";
foreach ($cssFiles as $cssFile) {
$buffer .= include($cssFile);
}
minifyCSS($buffer);
echo $buffer;
Well, nothing much here. Just added a include() there...
But it won't work as intended, unless you do like this, for every file:
Create a heredoc with all the content
Return it
Using the base stylesheet as an example:
<?php
//remember to escape the { chars
return <<<CSS
/* CSS header defined */
/* config.php included */
body\{
background-color: $priColor;
/* with an array */
background-image: url('{$images['print']}');
/* or */
background-image: url('$images[print]');
\}
CSS;
* Ignore the broken syntax highlight
And you are done.
No more nasty ob_start()!!!
Also, CSS comments use the /* */ syntax, // will be evaluated as an invalid CSS selector.
file_get_contents() will literally read the content of a file and place the content into a string. What you need to use is include(). This will parse the contents of the file.

create css with php laravel

i need create get css files with laraven in my controller, because i have one problem my return result is one normal file (text file) and not a css file
my routes.php file contain:
Route::get('/css/{css}.css', 'FileController#GetCss')
->where('css','[A-Za-z]+');
FileController.php:
<?php
class FileController extends \BaseController {
public function GetCss($css)
{
$file = File::get(app_path()."\css\\".$css.".css");
return $file;
}
}
and my css.css file contain:
body
{
background: #f00;
}
browser return is:
body{ background: #f00; }
and source (inspect element / ctrl+u):
body
{
background: #f00;
}
what I must do to work as a css file?
Your question need more clarification, I guess you are trying to build a CDN or something like that.
When you say "what I must do to work as a css file?", I think you need to specify a header for the response:
public function GetCss($css)
{
$file = File::get(app_path()."\css\\".$css.".css");
$response = Response::make($file);
$response->header('Content-Type', "text/css");
return $response;
}

Dynamic content in css file

I am modifying a web app. It allows the user to input hex values for label-color, background-color and font-color. When the user input the values and clicks "update template". I need to be able to update the background color, label color and font color depending on the hex values that the user inputs. I am storing the label-color, background-color and font-color along with other template information in a MySQL table. I can do the following in the all the .phtml files that control the view:
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$Title_Shiprequest = $Thetemplate->descriptionShipRequestTitle;
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
$clabel, $cbackground, $cfont are used for the color styling in the .phtml.
The problem is there are about 34 .phtml files. If I want to do it this way I have to find the div classes responsible for the colors and do the respective changes there. It sounds like a very inefficient and lengthy solution to me.
But there are about 4-5 classes in the css file where all the color values are defined and used. Its much easier and efficient for me to do something like the above mentioned code in css file (the only problem is it does not work in css file) and refer to them like below (i have renamed my common.css as common.php):
.panel1
{
width: auto;
height: 22px;
background-color: <?= $cbackground ?>;
padding: 5px;
}
When I try to include the code to fetch color information from the database it messes up all the formatting as if the program cant see my .css file. My hunch is that I am not allowed to instantiate an object inside a heredoc in a css even though I renamed it as common.php. What could be a workaround solution in this situation?
UPDATE:
Well I was already including header("Content-type: text/css"); But i tried the followings again just to make sure:
<?php
header("Content-type: text/css");
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
?>
<style type='text/css'>
.text4
{
color: <?=$clabel?>;// font and bkg colors are referred to likewise
}
</style>
Unfortunately this did not work. I also tried:
<?php
header("Content-type: text/css");
include('C:/sr/public/css/getdata.php');
?>
<style type='text/css'>
.text4
{
color: <?=$clabel?>;// font and bkg colors are referred to likewise
}
</style>
where getdata.php has the code:
<?php
$Idtemplate = $this->user->defaultTemplate;
include('C:/sr/application/models/Template.php');
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
$cbackground = $Thetemplate->descriptionBkgColor;
$cfont =$Thetemplate->descriptionFontColor;
?>
It did not work either. As a fourth variation I tried to define a function and call it from common.php:
<?php
function getLabelColor() {
$clabel = '#001122';
return $clabel;
}
function getBkgColor() {
$cbackground = '#002233';
return $cbackground;
}
function getFontColor() {
$cfont = '#004455';
return $cfont;
}
?>
where common.php has :
<?php
header("Content-type: text/css");
include('C:/sr/public/css/getdata.php');
?>
<style type='text/css'>
.text2
{
color: <?php echo getLabelColor();?>; /* Bkg and font colors are referred to likewise*/
}
</style>
Surprising this worked. But when I tried to replace
$clabel = '#001122';
(along with $cbackground and $cfont in the respective functions) with
$Idtemplate = $this->user->defaultTemplate;
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;
return ('#'.$clabel);
it stopped working. So I moved getdata.php to models made class that included all the above mentioned functions:
<?php
Class fetchData extends Template
{
function getLabelColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$clabel = $Thetemplate->descriptionlabelColor;//for future usage for dynamic color
return ('#'.$clabel);
}
function getBkgColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$cbackground = $Thetemplate->descriptionBkgColor;//for future usage for dynamic color
return ('#'.$cbackground);
}
function getFontColor() {
$Idtemplate = 101// I had assign a known value here. I was not able to use $this->user->defaultTemplate; Not sure why I wont be able to use $this
$Objtemplate = new Template();
$Thetemplate = $Objtemplate->fetchRow("id=" . $Idtemplate);
$cfont =$Thetemplate->descriptionFontColor;//for future usage for dynamic color
return ('#'.$cfont);
}
}
?>
I was calling the functions like below:
include('C:/sr/application/models/getdata.php');
$datafetchObj = new fetchData();
$clabel = $datafetchObj->getLabelColor(); //purple 51:0:153
$cbackground = $datafetchObj->getBkgColor(); //Light blue 102:102:204
$cfont = $datafetchObj->getFontColor();
This only worked from .phtml but not from common.php. I suppose common.php is NOT allowed to instantiate an object.
PS: This what my common.php call looks like:
<link rel="stylesheet" type="text/css" href="<?php echo $this->baseUrl();?>/css/common.php" />
You just use
<link rel="stylesheet" type="text/css" media="screen" href="/css/mycss.php" />
and then you can use php inside your css. you could add appropriate headers (text/css) with header in php.
// mycss.php
<?php
header("content-type:text/css");
?>
<style type='text/css'>
// Stylesheet
</style>
Add this line as a first line of page in common.php:
header("Content-type: text/css");
I was having the same problem as you, then I changed the hex color to the name of the color in the database and everything worked fine. I don't know why the hex color can't come out like other texts, but anyways, simply change the color the name:
E.I.: white for #FFFFFF
I hope that worked out for you.
EDIT: I thought that could be helpful too,
When inserting to database, use hexdec() http://www.php.net/manual/en/function.hexdec.php and when displaying from database, use dechex() http://php.net/manual/en/function.dechex.php .
dechex will return the hex without the hash (#) though, so you might need to print it like that:
<?php echo "#".dechex($decimal_number); ?>
I hope that was useful buddy.

Categories