mPDF (PHP) does not recognize html check mark - php

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');

Related

PHP file_exists method not working as expected

I am trying to set the background of the html body dynamically. Basically if a file exists, use it, otherwise use the default. But it keeps using the default regardless of whether the file exists or not.
<style>
body
{
padding-top: 50px;
background-image: url("<?php
clearstatcache();
if(file_exists("/profile_img/".$profileData["ID"]."_bg.jpg"))
{
echo "/profile_img/".$profileData["ID"]."_bg.jpg?". rand(5, 15);
}
else
{
//echo "/profile_img/".$profileData["ID"]."_bg.jpg?". rand(5, 15);
echo "/profile_img/default.jpg?". rand(5, 15);
}
?>");
background-size: cover;
background-position: 50% 50%;
}
</style>
I have tried using the file (the commented line) and it works. I can not see why this doesn't work
Some issues:
Using / will be absolute, causing it to look in the root directory.
Always check vars are set before using.
All that's changing is the filename, so you can use a ternary, which will reduce alot of that code.
<?php
$background = isset($profileData["ID"]) && file_exists('./profile_img/'.$profileData["ID"].'_bg.jpg')
? $profileData["ID"].'_bg.jpg' : 'default.jpg';
?>
<style>
body {
padding-top: 50px;
background-image: url("/profile_img/<?= $background.'?_='.microtime(true) ?>");
background-size: cover;
background-position: 50% 50%;
}
</style>
If it's still not working:
Check the file actually exists.

Alter CSS element in PHP variable or DOMDocument

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)

Remove comments from css file

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);

Keep div in desired place with css, external content

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'>";

phpsass returns a fatal error

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.

Categories