initial commit
[namibia] / module / Utility / src / Utility / Service / PdfTemplate.php
1 <?php
2 namespace Utility\Service;
3
4
5
6
7
8 #-> Fix tcpdf bad configuration.
9 define('K_TCPDF_EXTERNAL_CONFIG', true);
10 $_SERVER['DOCUMENT_ROOT'] = '/var/www/';
11 $kPathMain = getcwd() . '/vendor/tecnickcom/tcpdf/';
12 define('K_PATH_MAIN', $kPathMain);
13 $kPathUrl = $kPathMain;
14 if (isset($_SERVER['HTTP_HOST']) AND (!empty($_SERVER['HTTP_HOST']))) {
15         if (isset($_SERVER['HTTPS']) AND (!empty($_SERVER['HTTPS'])) AND strtolower($_SERVER['HTTPS'])!='off') {
16                 $kPathUrl = 'https://';
17         } else {
18                 $kPathUrl = 'http://';
19         }
20         $kPathUrl .= $_SERVER['HTTP_HOST'];
21         $kPathUrl .= str_replace('\\', '/', substr(K_PATH_MAIN, (strlen($_SERVER['DOCUMENT_ROOT']) - 1)));
22 }
23 define('K_PATH_URL', $kPathUrl);
24 define('K_PATH_FONTS', K_PATH_MAIN.'fonts/');
25 define('K_PATH_CACHE', K_PATH_MAIN.'cache/');
26 define('K_PATH_URL_CACHE', K_PATH_URL.'cache/');
27 define('K_PATH_IMAGES', K_PATH_MAIN.'images/');
28 define('K_BLANK_IMAGE', K_PATH_IMAGES.'_blank.png');
29 define('PDF_PAGE_FORMAT', 'A4');
30 define('PDF_PAGE_ORIENTATION', 'P');
31 define('PDF_CREATOR', 'HTML2PDF - TCPDF');
32 define('PDF_AUTHOR', 'HTML2PDF - TCPDF');
33 define('PDF_HEADER_TITLE', null);
34 define('PDF_HEADER_STRING', null);
35 define('PDF_HEADER_LOGO', null);
36 define('PDF_HEADER_LOGO_WIDTH', null);
37 define('PDF_UNIT', 'mm');
38 define('PDF_MARGIN_HEADER', 0);
39 define('PDF_MARGIN_FOOTER', 0);
40 define('PDF_MARGIN_TOP', 0);
41 define('PDF_MARGIN_BOTTOM', 0);
42 define('PDF_MARGIN_LEFT', 0);
43 define('PDF_MARGIN_RIGHT', 0);
44 define('PDF_FONT_NAME_MAIN', 'helvetica');
45 define('PDF_FONT_SIZE_MAIN', 10);
46 define('PDF_FONT_NAME_DATA', 'helvetica');
47 define('PDF_FONT_SIZE_DATA', 8);
48 define('PDF_FONT_MONOSPACED', 'courier');
49 define('PDF_IMAGE_SCALE_RATIO', 1);
50 define('HEAD_MAGNIFICATION', 1);
51 define('K_CELL_HEIGHT_RATIO', 1);
52 define('K_TITLE_MAGNIFICATION', 1);
53 define('K_SMALL_RATIO', 2/3);
54 define('K_THAI_TOPCHARS', true);
55 define('K_TCPDF_CALLS_IN_HTML', false);
56
57
58
59
60 /**
61  * Base reporting functionality.
62  * @author andre.fourie
63  */
64 abstract class PdfTemplate
65 {
66
67         /**
68          * @var \Doctrine\ORM\EntityManager
69          */
70         protected $em;
71         /**
72          * PDF title.
73          * @var string
74          */
75         protected $_title  = null;
76         /**
77          * PDF logo.
78          * @var string
79          */
80         protected $_logo  = '<h1 style="font-size:24px; margin:0 auto; text-align:center">EVALUATION SHEET</h1>
81                 <div style="width:100%"></div>';
82         /**
83          * PDF content.
84          * @var array
85          */
86         private $_html  = array();
87         /**
88          * Current page number.
89          * @var integer
90          */
91         protected $_page = 0;
92         /**
93          * Options passed.
94          * @var object
95          */
96         protected $_options = array();
97         /**
98          * Data passed.
99          * @var array
100          */
101         protected $_input = array();
102
103
104         /* ---------------------------------------------------------------------- *\
105          *      Standard Interface
106         \* ---------------------------------------------------------------------- */
107         /**
108          * Process standard format request.
109          * @param array $input
110          * @param array|object $options
111          */
112         public function process(array $input, $options)
113         {
114                 $this->em = \Utility\Registry::getEntityManager();
115                 $this->_input   = $input;
116                 $this->_options = $options;
117                 $this->build();
118                 return $this;
119         }
120
121         /**
122          * Build the content.
123          */
124         public function build() {}
125
126
127         /* ---------------------------------------------------------------------- *\
128          * Construction utilities.
129         \* ---------------------------------------------------------------------- */
130         /**
131          * Move to next page.
132          * @return \Utility\Service\PdfTemplate
133          */
134         public function nextPage()
135         {
136                 $this->_page++;
137                 return $this;
138         }
139
140         /**
141          * Append HTML to template.
142          * @param string $html
143          * @return \Utility\Service\PdfTemplate
144          */
145         public function append($html)
146         {
147                 if (!isset($this->_html[$this->_page]))
148                 {
149                         $this->_html[$this->_page] = '';
150                 }
151                 $this->_html[$this->_page] .= $html;
152                 return $this;
153         }
154
155         /**
156          * Retrieve new PDF data table.
157          * @param array $cellWidths
158          * @param string $tableStyle
159          * @param string $rowStyle
160          * @param string $cellStyle
161          * @return \Utility\Service\PdfElementTable
162          */
163         public function newTable(array $cellWidths, $tableStyle, $rowStyle, $cellStyle)
164         {
165                 return new PdfElementTable($cellWidths, $tableStyle, $rowStyle, $cellStyle);
166         }
167
168         /**
169          * Retrieve new PDF data table.
170          * Setup new signature section for PDF template.
171          * @param string|null $cellStyle
172          * @return \Utility\Service\PdfElementSignature
173          */
174         public function newSignatureLine($cellStyle = null)
175         {
176                 return new PdfElementSignature($cellStyle);
177         }
178
179         /* ---------------------------------------------------------------------- *\
180          * Specifically cater for PDF Template requirements.
181         \* ---------------------------------------------------------------------- */
182         /**
183          * Retrieve PDF title.
184          * @return string
185          */
186         public function getTitle()
187         {
188                 return $this->_title;
189         }
190
191
192
193         /**
194          * Retrieve PDF content.
195          * @return string
196          */
197         public function getHtml()
198         {
199
200                 $html = '';
201                 //$logo = '<img src="' . __DIR__ . '/../../../../../public/img/app/logos/logo-pdf.jpg" style="padding:0;margin:0;width:100%;" />';
202                 foreach ($this->_html as $page)
203                 {
204                         $html .= '<page style="padding:0;margin:0;width:100%;font-size:12px;">' . $this->_logo . $page . '</page>';
205                 }
206                 return $html;
207         }
208
209
210 }
211
212
213
214
215
216 /* ---------------------------------------------------------------------- *\
217  * PDF element handlers.
218 \* ---------------------------------------------------------------------- */
219
220 /**
221  * Helper utility to build PDF signature line(s).
222  * @author andre.fourie
223  */
224 class PdfElementSignature
225 {
226
227         /**
228          * @var array
229          */
230         protected $_data;
231         /**
232          * @var string
233          */
234         protected $_cellStyle = 'border-bottom: solid 1px #333;font-size:11px;font-weight:bold;';
235
236
237
238         /**
239          * Setup new signature section for PDF template.
240          * @param string|null $cellStyle
241          */
242         public function __construct($cellStyle = null)
243         {
244                 !is_null($cellStyle)
245                         && $this->_cellStyle = $cellStyle;
246         }
247
248         public function addSignatureLine($signatureLeft = null, $signatureMiddle = null, $signatureRight = null)
249         {
250                 $this->_data[] = array(
251                                 'Left'   => $signatureLeft,
252                                 'Pad1'   => null,
253                                 'Middle' => $signatureMiddle,
254                                 'Pad2'   => null,
255                                 'Right'  => $signatureRight
256                 );
257                 return $this;
258         }
259
260         public function addSignatureText($id, $text)
261         {
262                 $this->_data[$id] = $text;
263                 return $this;
264         }
265
266         /**
267          * Publish to HTML.
268          * @return string
269          */
270         public function publish()
271         {
272                 #-> Prepare params.
273                 $html = array();
274
275                 #-> Table header.
276                 $html[] = '<div style="position:absolute;bottom:50px;left:0;padding:0;margin:0;width:100%;">';
277                 $html[] = '<table cellpadding="0px" cellspacing="0px" style="border:0px;width:100%;">';
278
279                 #-> Table content.
280                 foreach ($this->_data as $rowId => $signatures)
281                 {
282                         if (is_numeric($rowId))
283                         {
284                                 $html[] = '<tr>';
285                                 $i = 0;
286                                 foreach ($signatures as $signature)
287                                 {
288                                         $i++;
289                                         $width = (2 == $i || 4 == $i)
290                                                 ? '5%'
291                                                 : '30%';
292                                         if (is_null($signature))
293                                         {
294                                                 $html[] = '<td style="padding:50px 0 0 0;width:' . $width . '">&nbsp;</td>';
295                                         }
296                                         else
297                                         {
298                                                 empty($signature)
299                                                         && $signature = '&nbsp;';
300                                                 $html[] = '<td style="padding:50px 0 0 0;width:' . $width . ';' . $this->_cellStyle. '">&nbsp;</td>';
301                                         }
302                                 }
303                                 $html[] = '</tr>';
304                                 $html[] = '<tr>';
305                                 $i = 0;
306                                 foreach ($signatures as $signature)
307                                 {
308                                         $i++;
309                                         $width = (2 == $i || 4 == $i)
310                                                 ? '5%'
311                                                 : '30%';
312                                         $value = is_null($signature)
313                                                 ? '&nbsp;'
314                                                 : $signature;
315                                         $html[] = '<td style="width:' . $width . ';font-size:11px;font-weight:bold;"><b>' . $value . '</b></td>';
316                                 }
317                                 $html[] = '</tr>';
318                         }
319                         else
320                         {
321                                 $html[] = '<tr>';
322                                 $html[] = '<td colspan="5" style="padding:50px 0 0 0;width:100%">' . $signatures . '</td>';
323                                 $html[] = '</tr>';
324                         }
325                 }
326
327                 #-> Table footer.
328                 $html[] = '</table>';
329                 $html[] = '</div>';
330
331                 #-> Done.
332                 return implode("\n", $html);
333         }
334
335
336 }
337
338
339
340
341
342 /**
343  * Helper utility to build PDF data table.
344  * @author andre.fourie
345  */
346 class PdfElementTable
347 {
348
349
350         /**
351          * @var array
352          */
353         protected $_titles = array();
354         /**
355          * @var array
356          */
357         protected $_columnHeaders;
358         /**
359          * @var string
360          */
361         protected $_titleStyle;
362         /**
363          * @var string
364          */
365         protected $_titleRowStyle;
366         /**
367          * @var string
368          */
369         protected $_tableStyle;
370         /**
371          * @var string
372          */
373         protected $_rowStyle;
374         /**
375          * @var string
376          */
377         protected $_cellStyle;
378         /**
379          * @var array
380          */
381         protected $_cellWidths;
382         /**
383          * @var array
384          */
385         protected $_data;
386
387
388
389         /**
390          * Setup new data table for PDF template.
391          * @param array $cellWidths
392          * @param string $tableStyle
393          * @param string $rowStyle
394          * @param string $cellStyle
395          */
396         public function __construct(array $cellWidths, $tableStyle, $rowStyle, $cellStyle)
397         {
398                 $this->_tableStyle = $tableStyle;
399                 $this->_rowStyle   = $rowStyle;
400                 $this->_cellStyle  = $cellStyle;
401                 $this->_cellWidths = $cellWidths;
402         }
403
404         /**
405          * Add table title.
406          * @param string $title
407          * @param string|null $titleCellStyle
408          * @param string|null $titleRowStyle
409          * @return \Utility\Service\PdfElementTable
410          */
411         public function addTitle($title, $titleCellStyle = null, $from = null, $to = null)
412         {
413                 $this->_titles[] = array(
414                                 'Title' => $title,
415                                 'Style' => $titleCellStyle,
416                                 'From'  => $from,
417                                 'To'    => $to
418                 );
419                 return $this;
420         }
421
422         /**
423          * Add table title.
424          * @param array $columnHeaders
425          * @param string|null $cellStyle
426          * @return \Utility\Service\PdfElementTable
427          */
428         public function setColumnHeaders(array $columnHeaders, array $columnSizes, $cellStyle = null)
429         {
430                 $this->_columnHeaders = array(
431                                 'Columns' => $columnHeaders,
432                                 'Sizes'   => $columnSizes,
433                                 'Style'   => $cellStyle
434                 );
435                 return $this;
436         }
437
438         /**
439          * Set value for specific cell.
440          * @param integer $row
441          * @param integer $column
442          * @param unknown $value
443          * @return \Utility\Service\PdfElementTable
444          */
445         public function setCellValue($row, $column, $value)
446         {
447                 $this->_data[$row][$column] = is_null($value) || empty($value)
448                         ? '&nbsp;'
449                         : $value;
450                 return $this;
451         }
452
453         /**
454          * Set dataset.
455          * @param array $dataSet
456          * @return \Utility\Service\PdfElementTable
457          */
458         public function setDataSet(array $dataSet)
459         {
460                 $this->_data = $dataSet;
461                 return $this;
462         }
463
464         /**
465          * Add a key => value dataset to the table.
466          * @param array $dataset
467          * @param number $startAtColumn
468          * @param string $keyStyle
469          * @param string $valueStyle
470          * @return \Utility\Service\PdfElementTable
471          */
472         public function addKeyValueDataSet(array $dataset, $startAtColumn = 0, $keyStyle = '', $valueStyle = '')
473         {
474                 $row = 0;
475                 $column = $startAtColumn;
476                 foreach ($dataset as $key => $value)
477                 {
478                         $this->_data[$row][$column] = '<span style="' . $keyStyle . '">' . $key . '</span>';
479                         $this->_data[$row][$column + 1] = '<span style="' . $valueStyle . '">' . $value . '</span>';
480                         $row++;
481                 }
482                 return $this;
483         }
484
485         /**
486          * Publish to HTML.
487          * @return string
488          */
489         public function publish()
490         {
491                 #-> Establish table width.
492                 $tableWidth = 0;
493                 $numColumns = count($this->_cellWidths);
494                 foreach ($this->_cellWidths as $columnWidth)
495                 {
496                         $tableWidth += $columnWidth;
497                 }
498
499                 #-> Prepare params.
500                 $html = array();
501
502                 #-> Table header.
503                 $html[] = '<table cellpadding="0px" cellspacing="0px" style="width:' . $tableWidth . '%;' . $this->_tableStyle . '">';
504
505                 #-> Table title.
506                 if (!empty($this->_titles))
507                 {
508                         $html[] = '<tr>';
509                         $column = 0;
510                         foreach ($this->_titles as $title)
511                         {
512                                 if ($title['From'] > $column)
513                                 {
514                                         $html[] = '<td colspan="' . ($title['From'] - $column) . '">&nbsp;</td>';
515                                 }
516                                 $cellStyle = !is_null($title['Style'])
517                                         ? $title['Style']
518                                         : $this->_cellStyle;
519                                 $html[] = '<td colspan="' . ($title['To'] - $title['From'] + 1) . '" style="' . $cellStyle . '">';
520                                 $html[] = $title['Title'];
521                                 $html[] = '</td>';
522                                 $column = $title['To'] + 1;
523                         }
524                         $html[] = '</tr>';
525                 }
526
527                 #-> Column headers.
528                 if (!is_null($this->_columnHeaders))
529                 {
530                         $cellStyle = !is_null($this->_columnHeaders['Style'])
531                                 ? $this->_columnHeaders['Style']
532                                 : $this->_cellStyle;
533                         $html[] = '<tr>';
534                         foreach ($this->_columnHeaders['Columns'] as $key => $title)
535                         {
536                                 $width = $this->_columnHeaders['Sizes'][$key];
537                                 $html[] = '<td style="width:' . $width . '%;' . $cellStyle . '">' . $title . '</td>';
538                         }
539                         $html[] = '</tr>';
540                 }
541
542                 #-> Table content.
543                 foreach ($this->_data as $rowId => $rowData)
544                 {
545                         $html[] = '<tr style="' . $this->_rowStyle. '">';
546                         $column = 0;
547                         for ($column = 0; $column < $numColumns; $column++)
548                         {
549                                 $value = isset($rowData[$column])
550                                         ? $rowData[$column]
551                                         : '&nbsp;';
552                                 $width = $this->_cellWidths[$column];
553                                 $html[] = '<td style="width:' . $width . '%;' . $this->_cellStyle. '">' . $value . '</td>';
554                         }
555                         $html[] = '</tr>';
556                 }
557
558                 #-> Table footer.
559                 $html[] = '</table>';
560
561                 #-> Done.
562                 return implode("\n", $html);
563         }
564
565
566 }
567
568
569