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);
Related
i am trying to create a chart in PHP through pChart 2.3 class.
My doubt is on this function:
function autoOutput(string $FileName = "output.png", int $Compression = 6, $Filters = PNG_NO_FILTER)
{
if (php_sapi_name() == "cli") {
$this->Render($FileName, $Compression, $Filters);
} else {
$this->Stroke(TRUE, $Compression, $Filters);
}
}
Html Code:
<div id="filtri">
<?php include($_SERVER['DOCUMENT_ROOT'] . "/reportingBug/generaGrafico1.php");?>
<?php include($_SERVER['DOCUMENT_ROOT'] . "/reportingBug/recuperaTempiMediLavBug.php");?>
<?php include($_SERVER['DOCUMENT_ROOT'] . "/reportingBug/recuperaTempiMediBug.php");?>
<img src="temp/example.drawBarChart.spacing.png">
</div>
Php Script:
/* Render the picture (choose the best way) */
$myPicture->autoOutput("temp/example.drawBarChart.spacing.png");
?>
If i force the code in order to follow the if branch with Render function everything is working right
because it creates a PNG image in root folder and i can retrieve it from HTML.
but it goes through the else branch, so the stroke function is called.
In the case, i have two problems:
i don't know how to retrieve the PNG from HTML
i have a problem because the browser shows following:
I tried to use a phisical image (PNG file create on the server folder) but i think it's not correct because many user will access the application concurrently.
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'
}
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.
I am trying to configure HTMLPurifier to only display external links as plain text. I used DisplayLinkURI option but it display all links as a plain text. is there any configuration for that? here is my code:
$mySite='mysite';
$externalSite='external';
require_once 'include/htmlpurifier/library/HTMLPurifier.auto.php';
$Config = HTMLPurifier_Config::createDefault();
$Config->set('AutoFormat.DisplayLinkURI', true);
$purifier = new HTMLPurifier($Config);
$mySite= $purifier->purify($mySite);
$externalSite=$purifier->purify($externalSite);
echo $mySite;
echo $externalSite;
The output is
<a>mysite</a> (http://www.mysite.com/)
<a>external</a> (http://www.external.com/)
I want the output to be like this:
mysite
<a>external</a> (http://www.external.com/)
Update:
I want to keep external links for images without change. I only need to convert hyperlinks to plain text.
I believe this is the one you're looking for
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
There's an option named URI.DisableExternal and AutoFormat.Linkify. Set them both to TRUE and see what happens.
http://htmlpurifier.org/live/configdoc/plain.html#URI.DisableExternal
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.Linkify
And AutoFormat.DisplayLinkURI disables all the links. I suggest you use both the above instead of AutoFormat.DisplayLinkURI.
http://htmlpurifier.org/live/configdoc/plain.html#AutoFormat.DisplayLinkURI
Ok, I succeeded to add a custom injector to HTMLPurifier, here it is:
First, Create a "DisplayRemoteLinkURI.php" in "include\htmlpurifier\library\HTMLPurifier\Injector" and write this in it
<?php
class HTMLPurifier_Injector_DisplayRemoteLinkURI extends HTMLPurifier_Injector
{
public $name = 'DisplayRemoteLinkURI';
public $needed = array('a');
public function handleElement(&$token) {
}
public function handleEnd(&$token) {
if (isset($token->start->attr['href'])){
$url = $token->start->attr['href'];
if($this->is_remote($url)){
unset($token->start->attr['href']);
$token = array($token, new HTMLPurifier_Token_Text(" ($url)"));
}
} else {
// nothing to display
}
}
public function is_remote($path){
$urlvar = parse_url($path);
$remote_schemes = array("mailto");
$local_schemes = array("javascript");
if(in_array($urlvar["scheme"],$remote_schemes)){
return true;
}else if(in_array($urlvar["scheme"],$local_schemes)){
return false;
}else{
if(empty($urlvar["host"]) || $urlvar["host"]==$_SERVER["HTTP_HOST"]){
return false;
}else{
return true;
}
}
}
}
?>
And then create another file named "AutoFormat.DisplayRemoteLinkURI.txt" in "include\htmlpurifier\library\HTMLPurifier\ConfigSchema\schema" and add this :
AutoFormat.DisplayRemoteLinkURI
TYPE: bool
VERSION: 3.2.0
DEFAULT: false
--DESCRIPTION--
<p>
This directive turns on the in-text display of Remote URIs in <a> tags, and disables
those links. For example, example becomes
example (<a>http://example.com</a>).
</p>
--# vim: et sw=4 sts=4
After that, Add this line
require 'HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.includes.php
Then, Add this line
require_once $__dir . '/HTMLPurifier/Injector/DisplayRemoteLinkURI.php';
under
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
in include\htmlpurifier\library\HTMLPurifier.safe-includes.php
After these edits, if your files are at local, run cmd.exe and go to your php directory. Then run "include/HTMLPurifier/maintenance/generate-schema-cache.php" from php.exe.
Or if you want to do this via browser, rename your .htaccess file inside "include/HTMLPurifier/maintenance/" to something else for a while, then add this line inside "generate-schema-cache.php" on the first line after the <?php tag;
php_set_env("PHP_IS_CLI",true);
and then run this file from browser. After you see "Saving schema.. done!", rename your .htaccess file back.
Then in your script, use "AutoFormat.DisplayRemoteLinkURI" as config, and voila!
Note that the is_remote() function inside the first file I gave here might be not so good, and I couldn't find a script that checks if a link is remote or local, so you might alter it later if you need.
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; }");