From c11f3d84adf2ae9c61785f4efa88f0e76248174a Mon Sep 17 00:00:00 2001 From: Jared Hancock <jared@osticket.com> Date: Mon, 8 Dec 2014 08:50:55 -0600 Subject: [PATCH] pdf: Staff ticket printing uses 100% HTML template --- include/class.pdf.php | 251 +----------------- include/staff/templates/ticket-print.tmpl.php | 250 +++++++++++++++++ 2 files changed, 255 insertions(+), 246 deletions(-) create mode 100644 include/staff/templates/ticket-print.tmpl.php diff --git a/include/class.pdf.php b/include/class.pdf.php index 34973391f..9a7f0a700 100644 --- a/include/class.pdf.php +++ b/include/class.pdf.php @@ -30,17 +30,11 @@ class Ticket2PDF extends mPDF function Ticket2PDF($ticket, $psize='Letter', $notes=false) { global $thisstaff; - $this->ticket = $ticket; $this->includenotes = $notes; parent::__construct('', $psize); - $this->SetMargins(10,10,10); - $this->AliasNbPages(); - $this->AddPage(); - $this->cMargin = 3; - $this->_print(); } @@ -48,70 +42,6 @@ class Ticket2PDF extends mPDF return $this->ticket; } - function getLogoFile() { - global $ost; - - if (!function_exists('imagecreatefromstring') - || (!($logo = $ost->getConfig()->getClientLogo()))) { - return INCLUDE_DIR.'fpdf/print-logo.png'; - } - - $tmp = tempnam(sys_get_temp_dir(), 'pdf') . '.jpg'; - $img = imagecreatefromstring($logo->getData()); - // Handle transparent images with white background - $img2 = imagecreatetruecolor(imagesx($img), imagesy($img)); - $white = imagecolorallocate($img2, 255, 255, 255); - imagefill($img2, 0, 0, $white); - imagecopy($img2, $img, 0, 0, 0, 0, imagesx($img), imagesy($img)); - imagejpeg($img2, $tmp); - return $tmp; - } - - //report header...most stuff are hard coded for now... - function Header() { - global $cfg; - - //Common header - $logo = $this->getLogoFile(); - $this->Image($logo, $this->lMargin, $this->tMargin, 0, 20); - if (strpos($logo, INCLUDE_DIR) === false) - unlink($logo); - $this->SetFont('Arial', 'B', 16); - $this->SetY($this->tMargin + 20); - $this->SetX($this->lMargin); - $this->WriteCell(0, 0, '', "B", 2, 'L'); - $this->Ln(1); - $this->SetFont('Arial', 'B',10); - $this->WriteCell(0, 5, $cfg->getTitle(), 0, 0, 'L'); - $this->SetFont('Arial', 'I',10); - $this->WriteCell(0, 5, Format::daydatetime(null, false), 0, 1, 'R'); - $this->Ln(5); - } - - //Page footer baby - function Footer() { - global $thisstaff; - - $this->SetY(-15); - $this->WriteCell(0, 2, '', "T", 2, 'L'); - $this->SetFont('Arial', 'I', 9); - $this->WriteCell(0, 7, sprintf(__('Ticket #%1$s printed by %2$s on %3$s'), - $this->getTicket()->getNumber(), $thisstaff->getUserName(), date('r')), 0, 0, 'L'); - //$this->WriteCell(0,10,'Page '.($this->PageNo()-$this->pageOffset).' of {nb} '.$this->pageOffset.' '.$this->PageNo(),0,0,'R'); - $this->WriteCell(0, 7, sprintf(__('Page %d'), ($this->PageNo() - $this->pageOffset)), 0, 0, 'R'); - } - - function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') { - parent::Cell($w, $h, $txt, $border, $ln, $align, $fill, $link); - } - - function WriteText($w, $text, $border) { - - $this->SetFont('Arial','',11); - $this->MultiCell($w, 7, $text, $border, 'L'); - - } - function WriteHtml() { static $filenumber = 1; $args = func_get_args(); @@ -131,187 +61,16 @@ class Ticket2PDF extends mPDF } function _print() { + global $thisstaff, $cfg; if(!($ticket=$this->getTicket())) return; - $w =(($this->w/2)-$this->lMargin); - $l = 35; - $c = $w-$l; - - // Setup HTML writing and load default thread stylesheet - $this->WriteHtml( - '<style>'.file_get_contents(ROOT_DIR.'css/thread.css') - .'</style>', 1, true, false); - - $this->SetFont('Arial', 'B', 11); - $this->cMargin = 0; - $this->SetFont('Arial', 'B', 11); - $this->SetTextColor(10, 86, 142); - $this->WriteCell($w, 7,sprintf(__('Ticket #%s'),$ticket->getNumber()), 0, 0, 'L'); - $this->Ln(7); - $this->cMargin = 3; - $this->SetTextColor(0); - $this->SetDrawColor(220, 220, 220); - $this->SetFillColor(244, 250, 255); - $this->SetX($this->lMargin); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Status'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, (string)$ticket->getStatus(), 1, 0, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Name'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, (string)$ticket->getName(), 1, 1, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Priority'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->getPriority(), 1, 0, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Email'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->getEmail(), 1, 1, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Department'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->getDeptName(), 1, 0, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Phone'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->getPhoneNumber(), 1, 1, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Create Date'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, Format::datetime($ticket->getCreateDate()), 1, 0, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Source'), 1, 0, 'L', true); - $this->SetFont(''); - $source = ucfirst($ticket->getSource()); - if($ticket->getIP()) - $source.=' ('.$ticket->getIP().')'; - $this->WriteCell($c, 7, $source, 1, 0, 'L', true); - $this->Ln(12); - - $this->SetFont('Arial', 'B', 11); - if($ticket->isOpen()) { - $this->WriteCell($l, 7, __('Assigned To'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->isAssigned()?$ticket->getAssigned():' -- ', 1, 0, 'L', true); - } else { - - $closedby = __('unknown'); - if(($staff = $ticket->getStaff())) - $closedby = (string) $staff->getName(); - - $this->WriteCell($l, 7, __('Closed By'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $closedby, 1, 0, 'L', true); - } - - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Help Topic'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, $ticket->getHelpTopic(), 1, 1, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('SLA Plan'), 1, 0, 'L', true); - $this->SetFont(''); - $sla = $ticket->getSLA(); - $this->WriteCell($c, 7, $sla?$sla->getName():' -- ', 1, 0, 'L', true); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Last Response'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, Format::datetime($ticket->getLastRespDate()), 1, 1, 'L', true); - $this->SetFont('Arial', 'B', 11); - if($ticket->isOpen()) { - $this->WriteCell($l, 7, __('Due Date'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, Format::datetime($ticket->getEstDueDate()), 1, 0, 'L', true); - } else { - $this->WriteCell($l, 7, __('Close Date'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, Format::datetime($ticket->getCloseDate()), 1, 0, 'L', true); - } - - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($l, 7, __('Last Message'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c, 7, Format::datetime($ticket->getLastMsgDate()), 1, 1, 'L', true); - - $this->SetFillColor(255, 255, 255); - foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) { - $idx = 0; - foreach ($form->getAnswers() as $a) { - if (in_array($a->getField()->get('name'), - array('email','name','subject','phone','priority'))) - continue; - $this->SetFont('Arial', 'B', 11); - if ($idx++ === 0) { - $this->Ln(5); - $this->SetFillColor(244, 250, 255); - $this->WriteCell(($l+$c)*2, 7, $a->getForm()->get('title'), - 1, 0, 'L', true); - $this->SetFillColor(255, 255, 255); - } - if ($val = $a->toString()) { - $this->Ln(7); - $this->WriteCell($l*2, 7, $a->getField()->get('label'), 1, 0, 'L', true); - $this->SetFont(''); - $this->WriteCell($c*2, 7, $val, 1, 0, 'L', true); - } - } - } - $this->SetFillColor(244, 250, 255); - $this->Ln(10); - - $this->SetFont('Arial', 'B', 11); - $this->cMargin = 0; - $this->SetTextColor(10, 86, 142); - $this->WriteCell($w, 7,trim($ticket->getSubject()), 0, 0, 'L'); - $this->Ln(7); - $this->SetTextColor(0); - $this->cMargin = 3; - - //Table header colors (RGB) - $colors = array('M'=>array(195, 217, 255), - 'R'=>array(255, 224, 179), - 'N'=>array(250, 250, 210)); - //Get ticket thread - $types = array('M', 'R'); - if($this->includenotes) - $types[] = 'N'; - - if(($entries = $ticket->getThreadEntries($types))) { - foreach($entries as $entry) { - - $color = $colors[$entry['thread_type']]; - - $this->SetFillColor($color[0], $color[1], $color[2]); - $this->SetFont('Arial', 'B', 11); - $this->WriteCell($w/2, 7, Format::datetime($entry['created']), 'LTB', 0, 'L', true); - $this->SetFont('Arial', '', 10); - $this->WriteCell($w, 7, Format::truncate($entry['title'], 50), 'TB', 0, 'L', true); - $this->WriteCell($w/2, 7, $entry['name'] ?: $entry['poster'], 'TBR', 1, 'L', true); - $this->SetFont(''); - $text = $entry['body']->display('pdf'); - if($entry['attachments'] - && ($tentry=$ticket->getThreadEntry($entry['id'])) - && ($attachments = $tentry->getAttachments())) { - $files = array(); - foreach($attachments as $attachment) - if (!$attachment['inline']) - $files[]= $attachment['name']; - - if ($files) - $text.="<div>Files Attached: [".implode(', ',$files)."]</div>"; - $text.="<div>".sprintf(__('Files Attached: [%s]'),implode(', ',$files))."</div>"; - } - $this->WriteHtml('<div class="thread-body">'.$text.'</div>', 2, false, false); - $this->Ln(5); - } - } - - $this->WriteHtml('', 2, false, true); + ob_start(); + include STAFFINC_DIR.'templates/ticket-print.tmpl.php'; + $html = ob_get_clean(); + $this->WriteHtml($html, 0, true, true); } } ?> diff --git a/include/staff/templates/ticket-print.tmpl.php b/include/staff/templates/ticket-print.tmpl.php new file mode 100644 index 000000000..bd9ed2aa7 --- /dev/null +++ b/include/staff/templates/ticket-print.tmpl.php @@ -0,0 +1,250 @@ +<html> + +<head> + <style type="text/css"> +@page { + header: html_def; + footer: html_def; + margin: 15mm; + margin-top: 35mm; +} +.logo { + max-width: 220px; + max-height: 71px; + width: auto; + height: auto; + margin: 0; +} +#ticket_thread .message, +#ticket_thread .response, +#ticket_thread .note { + margin-top:10px; + border:1px solid #aaa; + border-bottom:2px solid #aaa; +} +#ticket_thread .header { + text-align:left; + border-bottom:1px solid #aaa; + padding:3px; + position: relative; +} +#ticket_thread .message .header { + background:#C3D9FF; +} +#ticket_thread .response .header { + background:#FFE0B3; +} +#ticket_thread .note .header { + background:#FFE; +} +#ticket_thread .info { + padding:5px; + background:#F4FAFF; + height:16px; + line-height:16px; +} + +table.meta-data { + width: 100%; +} +table.custom-data { + margin-top: 10px; +} +table.custom-data th { + width: 25%; +} +table.custom-data th, +table.meta-data th { + text-align: right; + background-color: #ddd; + padding: 3px 8px; +} +table.meta-data td { + padding: 3px 8px; +} +.faded { + color:#666; +} +.pull-left { + float: left; +} +.pull-right { + float: right; + position: absolute; + right: 0; +} +.flush-right { + text-align: right; +} +.flush-left { + text-align: left; +} +.ltr { + direction: ltr; + unicode-bidi: embed; +} +.headline { + border-bottom: 2px solid black; + font-weight: bold; +} +div.hr { + border-top: 0.2mm solid #bbb; + margin: 0.5mm 0; + font-size: 0.0001em; +} +<?php include ROOT_DIR . 'css/thread.css'; ?> + </style> +</head> +<body> + +<htmlpageheader name="def" style="display:none"> +<?php if ($logo = $cfg->getClientLogo()) { ?> + <img src="cid:<?php echo $logo->getKey(); ?>" class="logo"/> +<?php } else { ?> + <img src="<?php echo INCLUDE_DIR . 'fpdf/print-logo.png'; ?>" class="logo"/> +<?php } ?> + <div class="hr"> </div> + <table><tr> + <td class="flush-left"><?php echo (string) $ost->company; ?></td> + <td class="flush-right"><?php echo Format::db_daydatetime(Misc::gmtime()); ?></td> + </tr></table> +</htmlpageheader> + +<htmlpagefooter name="def" style="display:none"> + <hr class="tight faded"/> + <table width="100%"><tr><td class="flush-left"> + Ticket #<?php echo $ticket->getNumber(); ?> printed by + <?php echo $thisstaff->getUserName(); ?> on + <?php echo Format::db_daydatetime(Misc::gmtime()); ?> + </td> + <td class="flush-right"> + Page {PAGENO} + </td> + </tr></table> +</htmlpagefooter> + +<!-- Ticket metadata --> +<h1>Ticket #<?php echo $ticket->getNumber(); ?></h1> +<table class="meta-data" cellpadding="0" cellspacing="0"> +<tbody> +<tr> + <th><?php echo __('Status'); ?></th> + <td><?php echo $ticket->getStatus(); ?></td> + <th><?php echo __('Name'); ?></th> + <td><?php echo $ticket->getOwner()->getName(); ?></td> +</tr> +<tr> + <th><?php echo __('Priority'); ?></th> + <td><?php echo $ticket->getPriority(); ?></td> + <th><?php echo __('Email'); ?></th> + <td><?php echo $ticket->getEmail(); ?></td> +</tr> +<tr> + <th><?php echo __('Department'); ?></th> + <td><?php echo $ticket->getDept(); ?></td> + <th><?php echo __('Phone'); ?></th> + <td><?php echo $ticket->getPhoneNumber(); ?></td> +</tr> +<tr> + <th><?php echo __('Create Date'); ?></th> + <td><?php echo Format::db_datetime($ticket->getCreateDate()); ?></td> + <th><?php echo __('Source'); ?></th> + <td><?php echo $ticket->getSource(); ?></td> +</tr> +</tbody> +<tbody> + <tr><td colspan="4" class="spacer"> </td></tr> +</tbody> +<tbody> +<tr> + <th><?php echo __('Assigned To'); ?></th> + <td><?php echo $ticket->getAssigned(); ?></td> + <th><?php echo __('Help Topic'); ?></th> + <td><?php echo $ticket->getHelpTopic(); ?></td> +</tr> +<tr> + <th><?php echo __('SLA Plan'); ?></th> + <td><?php if ($sla = $ticket->getSLA()) echo $sla->getName(); ?></td> + <th><?php echo __('Last Response'); ?></th> + <td><?php echo Format::db_datetime($ticket->getLastResponseDate()); ?></td> +</tr> +<tr> + <th><?php echo __('Due Date'); ?></th> + <td><?php echo Format::db_datetime($ticket->getEstDueDate()); ?></td> + <th><?php echo __('Last Message'); ?></th> + <td><?php echo Format::db_datetime($ticket->getLastMessageDate()); ?></td> +</tr> +</tbody> +</table> + +<!-- Custom Data --> +<?php +foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) { + // Skip core fields shown earlier in the ticket view + // TODO: Rewrite getAnswers() so that one could write + // ->getAnswers()->filter(not(array('field__name__in'=> + // array('email', ...)))); + $answers = array_filter($form->getAnswers(), function ($a) { + return !in_array($a->getField()->get('name'), + array('email','subject','name','priority')); + }); + if (count($answers) == 0) + continue; + ?> + <table class="custom-data" cellspacing="0" cellpadding="4" width="100%" border="0"> + <tr><td colspan="2" class="headline flush-left"><?php echo $form->getTitle(); ?></th></tr> + <?php foreach($answers as $a) { + if (!($v = $a->display())) continue; ?> + <tr> + <th><?php + echo $a->getField()->get('label'); + ?>:</th> + <td><?php + echo $v; + ?></td> + </tr> + <?php } ?> + </table> + <?php + $idx++; +} ?> + +<!-- Ticket Thread --> +<h2><?php echo $ticket->getSubject(); ?></h2> +<div id="ticket_thread"> +<?php +$types = array('M', 'R'); +if ($this->includenotes) + $types[] = 'N'; + +if ($thread = $ticket->getThreadEntries($types)) { + $threadTypes=array('M'=>'message','R'=>'response', 'N'=>'note'); + foreach ($thread as $entry) { ?> + <div class="thread-entry <?php echo $threadTypes[$entry['thread_type']]; ?>"> + <table class="header" style="width:100%"><tr><td> + <span><?php + echo Format::db_datetime($entry['created']);?></span> + <span style="padding:0 1em" class="faded title"><?php + echo Format::truncate($entry['title'], 100); ?></span> + </td> + <td class="flush-right faded title" style="white-space:no-wrap"> + <?php + echo Format::htmlchars($entry['name'] ?: $entry['poster']); ?></span> + </td> + </tr></table> + <div class="thread-body"> + <div><?php echo $entry['body']->display('pdf'); ?></div> + <?php + if($entry['attachments'] + && ($tentry = $ticket->getThreadEntry($entry['id'])) + && ($links = $tentry->getAttachmentsLinks())) {?> + <div class="info"><?php echo $tentry->getAttachmentsLinks(); ?></div> + <?php + } ?> + </div> + </div> +<?php } +} ?> +</div> +</body> +</html> -- GitLab