From ce21d1a674258a649dfe83282d110d17488139fb Mon Sep 17 00:00:00 2001 From: Peter Rotich <peter@osticket.com> Date: Sun, 27 May 2012 19:38:42 -0400 Subject: [PATCH] PDF export class - Ticket2PDF + print-logo --- include/class.pdf.php | 213 ++++++++++++++++++++++++++++++++++++ include/fpdf/print-logo.png | Bin 0 -> 11684 bytes 2 files changed, 213 insertions(+) create mode 100644 include/class.pdf.php create mode 100644 include/fpdf/print-logo.png diff --git a/include/class.pdf.php b/include/class.pdf.php new file mode 100644 index 000000000..4d5fe5f76 --- /dev/null +++ b/include/class.pdf.php @@ -0,0 +1,213 @@ +<?php +/********************************************************************* + class.pdf.php + + Ticket PDF Export + + Peter Rotich <peter@osticket.com> + Copyright (c) 2006-2012 osTicket + http://www.osticket.com + + Released under the GNU General Public License WITHOUT ANY WARRANTY. + See LICENSE.TXT for details. + + vim: expandtab sw=4 ts=4 sts=4: +**********************************************************************/ + +define('THIS_DIR', str_replace('\\\\', '/', realpath(dirname(__FILE__))) . '/'); //Include path.. +define('FPDF_DIR', THIS_DIR . 'fpdf/'); +define('FPDF_FONTPATH', FPDF_DIR . 'font/'); //fonts directory. +session_cache_limiter('private'); +require (FPDF_DIR . 'fpdf.php'); + +class Ticket2PDF extends FPDF +{ + + var $includenotes = false; + + var $pageOffset = 0; + + var $ticket = null; + + function Ticket2PDF($ticket, $notes=false) { + + parent::FPDF(); + + $this->ticket = $ticket; + + $this->includenotes = $notes; + $this->setMargins(5, 2, 2); + $this->AliasNbPages(); + $this->AddPage(); + $this->cMargin = 3; + $this->_print(); + } + + function getTicket() { + return $this->ticket; + } + + //report header...most stuff are hard coded for now... + function Header() { + global $cfg; + + //Common header + $this->Ln(2); + $this->SetFont('Times', 'B', 16); + $this->Image(FPDF_DIR . 'print-logo.png', null, 5, 0, 20); + $this->SetX(200, 10); + $this->Cell(0, 10, "Support Ticket System", 0, 1, 'R', 0); + //$this->SetY(40); + $this->SetXY(60, 20); + $this->SetFont('Arial', 'B', 16); + $this->Cell(0, 3, 'Ticket #'.$this->getTicket()->getExtId(), 0, 2, 'L'); + $this->SetX($this->lMargin); + $this->Cell(0, 3, '', "B", 2, 'L'); + $this->SetFont('Arial', 'I',10); + $this->Cell(0, 5, 'Generated on '.Format::date($cfg->getDateTimeFormat(), Misc::gmtime(), $_SESSION['TZ_OFFSET'], $_SESSION['TZ_DST']), 0, 0, 'L'); + $this->Cell(0, 5, 'Date & Time based on GMT '.$_SESSION['TZ_OFFSET'], 0, 1, 'R'); + $this->Ln(10); + } + + //Page footer baby + function Footer() { + global $thisstaff; + + $this->SetY(-10); + $this->Cell(0, 2, '', "T", 2, 'L'); + $this->SetFont('Arial', 'I', 9); + $this->Cell(0, 7, 'Ticket printed by '.$thisstaff->getUsername().' on '.date('r'), 0, 0, 'L'); + //$this->Cell(0,10,'Page '.($this->PageNo()-$this->pageOffset).' of {nb} '.$this->pageOffset.' '.$this->PageNo(),0,0,'R'); + $this->Cell(0, 7, 'Page ' . ($this->PageNo() - $this->pageOffset), 0, 0, 'R'); + } + + function WriteText($w, $text, $border) { + + $this->SetFont('Times','',11); + $this->MultiCell($w, 5, $text, $border, 'L'); + + } + + function _print() { + + if(!($ticket=$this->getTicket())) + return; + + $w =(($this->w/2)-$this->lMargin); + $l = 40; + $c = $w-$l; + $this->setDrawColor(220, 220, 220); + $this->setFillColor(244, 250, 255); + $this->setX($this->lMargin); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Status', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getStatus(), 1, 0, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Name', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getName(), 1, 1, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Priority', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getPriority(), 1, 0, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Email', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getEmail(), 1, 1, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Department', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getDeptName(), 1, 0, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Phone', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getPhoneNumber(), 1, 1, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Create Date', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, Format::db_datetime($ticket->getCreateDate()), 1, 0, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Source', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, ucfirst($ticket->getSource()), 1, 0, 'L', true); + $this->Ln(15); + + $this->SetFont('Arial', 'B', 11); + if($ticket->isOpen()) { + $this->Cell($l, 7, 'Assigned To', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->isAssigned()?implode('/', $ticket->getAssignees()):' -- ', 1, 0, 'L', true); + } else { + + $closedby = 'unknown'; + if(($staff = $ticket->getStaff())) + $closedby = $staff->getName(); + + $this->Cell($l, 7, 'Closed By', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $closedby, 1, 0, 'L', true); + } + + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Subject', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getSubject(), 1, 1, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Last Response', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, Format::db_datetime($ticket->getLastRespDate()), 1, 0, 'L', true); + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Help Topic', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, $ticket->getHelpTopic(), 1, 1, 'L', true); + $this->SetFont('Arial', 'B', 11); + if($ticket->isOpen()) { + $this->Cell($l, 7, 'Due Date', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, Format::db_datetime($ticket->getDueDate()), 1, 0, 'L', true); + } else { + $this->Cell($l, 7, 'Close Date', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, Format::db_datetime($ticket->getCloseDate()), 1, 0, 'L', true); + } + + $this->SetFont('Arial', 'B', 11); + $this->Cell($l, 7, 'Last Message', 1, 0, 'L', true); + $this->SetFont(''); + $this->Cell($c, 7, Format::db_datetime($ticket->getLastMsgDate()), 1, 1, 'L', true); + $this->Ln(10); + + //Table header colors (RGB) + $colors = array('M'=>array(195, 217, 255), + 'R'=>array(255, 224, 179), + 'N'=>array(250, 250, 210)); + //Get ticket thread + if(($entries = $ticket->getThreadWithNotes())) { + foreach($entries as $entry) { + + $color = $colors[$entry['thread_type']]; + + $this->setFillColor($color[0], $color[1], $color[2]); + $this->SetFont('Arial', 'B', 11); + $this->Cell($w/2, 7, Format::db_datetime($entry['created']), 'LTB', 0, 'L', true); + $this->SetFont('Arial', '', 10); + $this->Cell($w, 7, $entry['title'], 'TB', 0, 'L', true); + $this->Cell($w/2, 7, $entry['poster'], 'TBR', 1, 'L', true); + $this->SetFont(''); + $text= $entry['body']; + if($entry['attachments'] + && ($attachments = $ticket->getAttachments($entry['id'], $entry['thread_type']))) { + foreach($attachments as $attachment) + $files[]= $attachment['name']; + + $text="\n\n[".implode(', ',$files)."]\n"; + } + $this->WriteText($w*2, $text, 1); + $this->Ln(5); + } + } + + } +} +?> diff --git a/include/fpdf/print-logo.png b/include/fpdf/print-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6526ebe0a15f393382e0339b38cef8422d7ff471 GIT binary patch literal 11684 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 literal 0 HcmV?d00001 -- GitLab