I'm building emails from external variables of CSS and HTML and then combining them as inline styles. Before they are combined, however, I want to alter the CSS.
In the below, I want to remove the padding and margin from the body. How should I do this - preg_match or is there something "cleaner"?
$css = "body {
background: #fff;
color: #000;
padding: 0;
margin: 0;
font: 83%/1.4 verdana,sans-serif;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
a, a:link, a:visited, a:hover, a:active {
background: transparent;
text-decoration: none;
cursor: pointer;
}";
Also, it's well worth mentioning that I am getting the CSS (then inline-styling) like this with the below so maybe the DOMDocument can help me - that seems cleaner, but I don't know where to start.
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
$dom = new DOMDocument();
#$dom->loadHTML($row['htmlbody']); //from a database
$cssobj = $dom->getElementsByTagName('style');
$bodyobj = $dom->getElementsByTagName('body')->item(0);
$plainbody = new DOMDocument();
foreach ($bodyobj->childNodes as $child){
$plainbody->appendChild($plainbody->importNode($child, true));
}
$body = $plainbody->saveHTML();
$css = $cssobj->item(0)->nodeValue;
$cssToInlineStyles = new CssToInlineStyles();
$originalemail = $cssToInlineStyles->convert(
$body,
$css
);
If you know the exact text that you want to remove, you can use a str_replace() from php. Example: $str_replace('margin:0;','',$css)
or
$str = preg_replace('/margin:(.*?);/', '', $css)
Related
I am showing a table in HTML on my web page where a check mark is shown properly (I am using ✔ for the bold check mark).
I am using classic-asp to display the HTML. The html buildup (tableOutput) is then posted to a PHP script ($output = $_POST["output"]) that uses mPDF.php (version 6.0) to print to PDF the same HTML table and somehow the check mark wont print correctly (%u2714 in printed on my PDF). All the rest of the table is printed correctly, only the check mark has a problem.
I tried adding the Symbola.ttf and Symbola_hint.ttf fonts in the mpdf\ttfonts folder but it didnt do the trick.
HTML (classic-asp):
tableOutput = tableOutput & "<TD class='center pass_x' style='font-family:symbola;'>✔</TD>"
PHP (create_report_pdf.php):
$output = $_POST["output"]; //This is the html buildup tableOutput discussed previously
$header = Irrelevant;
$footer= Irrelevant;
$mpdf = new mPDF( 'utf-8', 'A4-L', 0, '', 5, 5, 20, 20);
$mpdf->allow_charset_conversion = true;
$mpdf->WriteHTML($style,1);
$mpdf->SetHTMLHeader( $header );
$mpdf->SetHTMLFooter( $footer );
$mpdf->WriteHTML( $output );
$mpdf->Output($temp ,'F' );
config_fonts.php (I addded symbola.ttf and Symbola_hint.ttf in the mpdf\ttfonts folder):
$this->fontdata = array (
"symbola" => array (
'R' => "Symbola.ttf",
'I' => "Symbola_hint.ttf",
),
CSS (PHP $style variable points to create_report_pdf.css):
.report-table{
border: 1px solid black;
border-collapse: collapse;
font-size: 7pt;
width: 100%;
}
th,td{
font-size: 7pt;
border: 1px solid black !important;
vertical-align : middle;
}
.center{ text-align: center; vertical-align: middle; }
INPUT{
border-color:#ffffff !important;
}
.pf{ width: 45px; }
.fix-cell{ width: 90px; }
.dr-column, .dr-input{ width: 100px; }
.comments, .comments-input{ width: 130px; }
Thank you very much for your help
There are two possible solutions:
Replacing manually the %u2714 with the respective html entity ✔ by doing the following:
$output = str_replace('%u2714', '✔', $output);
Implement more generic approach that will handle all such special chars. The approach is based on the fact that %uXXXX is a non-standard notation scheme for URL-encoding Unicode characters. So you need to convert %uXXXX notation to HTML entity notation &#xXXXX; and then this can be decoded to actual UTF-8 by html_entity_decode.
$output = preg_replace('/%u([0-9A-F]+)/', '&#x$1;', $output);
$output = html_entity_decode($output, ENT_COMPAT, 'UTF-8');
found a couple answers here on StackOverflow and used them as my models, but I must be missing something. I'm trying to set a couple of background colors dynamically in CSS based on what is in my database, but it's not working - when I check Inspect Element in Chrome, background-color has a line through it and a warning mark for 'Invalid property value'.
Here's my code; it's in two separate files - the first is in the header include file, and the second is in the linked .php / css-esque file.
Header include: [Edited 4/29 to include session code]
session_start();
// check if $_SESSION was set before
if (!isset($_SESSION['email'])) {
header("Location: bad_login.php");
exit();
}
$_SESSION['companyid'] = $_POST['companyid'];
$companyID = $_SESSION['companyid'];
$email = $_SESSION['email'];
require_once('../includes/_connection.inc.php');
$connect = dbConnect('read');
$sql = 'SELECT colorone, colortwo, logo
FROM companies
WHERE companyid = ' . $companyID;
$result = $connect->query($sql) or die(mysqli_error());
$row = $result->fetch_assoc();
$colorOne = '#' . $row['colorone'];
$colorTwo = '#' . $row['colortwo'];
$carrierLogo = '/companylogos/' . $row['logo'];
PHP/CSS file:
<?php header("Content-type: text/css");
?>
#main {
width: 85%;
margin: 0 auto;
padding: 0.75em 0;
}
#colorOne {
width: 100%;
height: 12px;
background-color: <?php echo $colorOne; ?>;
}
#colorTwo {
width: 100%;
height: 7px;
background-color: <?php echo $colorTwo; ?>;
}
EDIT 4/29:
This is the CSS generated:
#main {
width: 85%;
margin: 0 auto;
padding: 0.75em 0;
}
#colorOne {
width: 100%;
height: 12px;
background-color: ;
}
#colorTwo {
width: 100%;
height: 7px;
background-color: ;
}
I also echoed the variable back in the html so I know that there should be something in the variable. Should I be opening the database and assigning the variable inside the css.php file?
CSS/PHP is linked this way in header:
<link type="text/css" rel="stylesheet" href="../css/carrier.php">
Instead of using the .css file extension, use .php
in the html file: is it linked to .php?
<link rel='stylesheet' type='text/css' href='css/style.php' />
in the style.php add
<?php
header("Content-type: text/css; charset: UTF-8");
?>
Now you can set up variables for whatever you like:
source
Edit:
Don't forget about session_start(); since you're using sessions (I don't understand how, since nothing gets posted to css/carrier.php you should rather have it in session from a different file & then just use the $companyID = $_SESSION['companyid'];
$email = $_SESSION['email'];).
is this the way your code looks?
<?php
session_start();
header("Content-type: text/css; charset: UTF-8");
$_SESSION['companyid'] = $_POST['companyid'];
$companyID = $_SESSION['companyid'];
$email = $_SESSION['email'];
require_once('../includes/_connection.inc.php');
$connect = dbConnect('read');
$sql = 'SELECT colorone, colortwo, logo
FROM companies
WHERE companyid = ' . $companyID;
$result = $connect->query($sql) or die(mysqli_error());
$row = $result->fetch_assoc();
$colorOne = '#' . $row['colorone'];
$colorTwo = '#' . $row['colortwo'];
$carrierLogo = '/companylogos/' . $row['logo'];
?>
#main {
width: 85%;
margin: 0 auto;
padding: 0.75em 0;
}
#colorOne {
width: 100%;
height: 12px;
background-color: <?php echo $colorOne; ?>;
}
#colorTwo {
width: 100%;
height: 7px;
background-color: <?php echo $colorTwo; ?>;
}
The answer of yesitsme is correct. Other thing you can do is that each storage changes in the database, run the process of creating this "new" CSS file with the appropriate .css extension.
What if with every request you create a new CSS file?
I mean, you have two paths, when creating the first call to the Web and update it from time to time, either, at the time you keep the data in the database associating it to a script.
With this new CSS and stored is generated through fwrite () and other functions that PHP has to manage files, keep the name of the CSS created in the BDD and then in your place the link as appropriate.
I have to read a css file and remove its commentaries, so i've decided to use the preg_replace function from php:
$original = '
/*
foo
*/
.test, input[type="text"]{ color: blue; }
/* bar */
a:hover{
text-decoration: underline;
color: red;
background: #FFF;
}';
echo preg_replace('/\/\*.*\*\//s', '', $original);
the problem is that its losing the line .test, input[type="text"]{ color: blue; }
Change .* to .*?.
echo preg_replace('#/\*.*?\*/#s', '', $original);
This will only remove /* up to the closest */ rather than the furthest.
I would approach it as follows:
\/\*((?!\*\/).*?)\*\/
\/\* # Start-of-comment
((?!\*\/).*?) # Any character 0 or more times, lazy,
# without matching an end-of-comment
\*\/ # End-of-comment
Demo
Try this:
$buffer = preg_replace('/\*[^*]*\*+([^/][^*]*\*+)*/', '', $buffer);
It doesn't work for //Comments here, but it works for the rest of /* Comment here */, even for multiple lines.
for //Comments here, use this one:
$buffer = preg_replace('/\/\*.*?\*\//s', '', $buffer);
Here is my problem.
I have a function, PHP class side, that reads all data from one table, create all divs with specific CSS ids, puts the data in place, and in one of them the data comes from an external source, an external php file.
So I do this in the code:
$Return .= "</div><div id='PostTitleComplete'><strong>Post Completo</strong></div><div id='PostText'>";
$Return .= include($row['PathFile']);
$Return .= "</div><div id='PostData'>";
All divs are opening and closing properly, all data worked correctly until i changed the data that used to be loaded fom the table to the div here the included file is know.
The external file only have HTML code generated by HTML copy from Visual studio and its all good to, ive used to use that html code in other places, no problem till know.
So, the CSS are the ones that follow:
This is the CSS used to hold the included file:
#PostText {
text-align:center;
padding: 15px;
word-wrap: break-word;
}
This is the parent of the above one:
#PostBody {
border: #00C 1px solid;
width:80%;
background:#FFFFFF;
float:left;
}
and this ones are the CSS from the included file:
One div includes the one, just like the name says.
#FirstOne {
border: #000080 1px solid;
color: #000;
font-family: 'Courier New', Courier, Monospace;
font-size: 9pt;
}
#SecondOne {
background: #000080;
color: #fff;
font-family: Verdana, Tahoma, Arial, sans-serif;
font-weight: bold;
padding: 2px 5px;
}
I used this same structure in one blog, but instead of an include file I used data from the table, so i think the problem are from the CSS. This is the result i get. This Giang Div is totally adjustable to the screen size, but it stays up there instead of here the arrow points and here the include is printed.
Well...
The value 1 is returned because the include-statement was performed successfully.
If the included file doesn't contain any code that needs to run, you can use file_get_contents():
$Return .= "</div><div id='PostTitleComplete'><strong>Post Completo</strong></div><div id='PostText'>";
$Return .= file_get_contents($row['PathFile']);
$Return .= "</div><div id='PostData'>";
As a reference, if the include file does have code that has to be executed, use output buffering:
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
return ob_get_clean();
}
return false;
}
$Return .= "</div><div id='PostTitleComplete'><strong>Post Completo</strong></div><div id='PostText'>";
$Return .= get_include_contents($row['PathFile']);
$Return .= "</div><div id='PostData'>";
Above code is taken from the PHP-manual (include-statement, example 6)
Instead of using incude try using file_get_content()
$Return .= "</div><div id='PostTitleComplete'><strong>Post Completo</strong></div>";
$Return .= "<div id='PostText'>";
$Return .= file_get_content($row['PathFile']);
$Return .= "</div><div id='PostData'>";
I am using a very simple code to test phpsass
$sass = new SassParser();
$c = file_get_contents('/_www/_projects/cdn/public_html/test/test.sass');
$css = $sass->toCss($c);
The sass file is very basic:
$blue: #3bbfce;
$margin: 16px;
table.hl {
margin: 2em 0;
td.ln {
text-align: right;
}
}
li {
font: {
family: serif;
weight: bold;
size: 1.2em;
}
}
.content-navigation {
border-color: $blue;
color:
darken($blue, 9%);
}
.border {
padding: $margin / 2;
margin: $margin / 2;
border-color: $blue;
}
And I get the following error:
Fatal error: Uncaught exception 'SassNumberException' with message ' in D:\_www\_git\phpsass\script\literals\SassNumber.php on line 201
SassNumberException: Number must be a number: Array::26 Source: padding: $margin / 2; in D:\_www\_git\phpsass\script\literals\SassNumber.php on line 201
If it can help, there's also the following notice thrown before (I tried to change the error_reporting level but having the notice disappear of course didn't solve the problem):
Notice: Array to string conversion in D:\_www\_git\phpsass\SassException.php on line 25
If I use the same sass code against their online PHP compiler at http://www.phpsass.com/try/ it compiles correctly... I don't get it
Take a look at the SassParser class. The function toCss() has a second parameter called $isFile which by default is true:
public function toCss($source, $isFile = true) {
return $this->parse($source, $isFile)->render();
}
If you notice, you're passing in the source not the filename. You can either pass in the filename like so:
$sass = new SassParser();
$c = '/_www/_projects/cdn/public_html/test/test.sass';
$css = $sass->toCss($c);
Or do what you're trying to do but with an additional parameter on toCss():
$sass = new SassParser();
$c = file_get_contents('/_www/_projects/cdn/public_html/test/test.sass');
$css = $sass->toCss($c, false);
Your sass file is not really sass at all; this would be the correct syntax, basically take out all the trailing semi-colons:
$blue: #3bbfce
$margin: 16px
table.hl {
margin: 2em 0
td.ln {
text-align: right
}
}
li {
font: {
family: serif
weight: bold
size: 1.2em
}
}
.content-navigation {
border-color: $blue
color
darken($blue, 9%)
}
.border {
padding: $margin / 2
margin: $margin / 2
border-color: $blue
}
Or, like you suggested:
$sass = new SassParser(['syntax' => SassFile::SCSS]);
In fact that was a pure syntaxic problem. I tried to remove the variables from the sass code, and realized it worked - not well (margin: 2em 0 became margin: 20) but there was no error anymore.
The sass snippets that I took from http://sass-lang.com/ were not sass but scss format. The SassParser class has a parameter called syntax, which is set to 'sass' by default and needs to be set to scss when calling $scss = new SassParser(['syntax' => 'scss']).
However I needed to parse a string, not a file, but if you pass a file with a scss extension you don't need this extra parameter.