// appunti sul API tcpdf
<?php
namespace PDFEtichettaFornitori {
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
// ritorna paginate di label data
class ItemValRecPager {
const LABEL_NUM_PER_PAGE = 10;
protected $data = [];
// quante pagine ha il report
public function getPagesCount() {
return ceil(count($this->data) / self::LABEL_NUM_PER_PAGE );
}
public function getRecordByIdx($idx) {
if (isset($this->data[$idx])) {
return $this->data[$idx];
}
return null;
}
// real data from database
public function initData(array $a_rec) {
foreach ($a_rec as $rec) {
$this->data[] = new ItemValRec($rec);
}
}
//----------------------------------------------------------------------------
// test data generator
//----------------------------------------------------------------------------
// random test data
public function initRandomData($num_etichette) {
for ($i = 0; $i < $num_etichette; $i++) {
$rec = [
'code' => 'QC12345C',
'image' => self::getRandImg(),
'color' => 'Grigio-Nero / Grey-Black',
'barcode' => '8058129030004',
'lotto' => '22187',
'compat_list' => self::getCompatList(),
];
$this->data[] = new ItemValRec($rec);
}
}
protected static function getRandImg() {
$a_images = [
'QF38004.jpg', // ratio:2
'QG37133.jpg', // ratio:3
];
$rand_i = rand(0, count($a_images) - 1);
return $a_images[$rand_i];
}
// genera una lista casuale di compatibilità auto
protected static function getCompatList() {
$a_compat = [];
static $c = 1;
$c++;
$c = min($c, 8); // al massimo 8 label
for ($i = 0; $i < $c; $i++) {
$a_compat[] = "DACIA DUSTER 0$i/10>05/12";
}
return $a_compat;
}
}
// mantiene i valori da stampare nell'etichetta
// eventuali formattazioni o elaborazioni sui dati
class ItemValRec {
protected $code;
protected $image;
protected $color;
protected $barcode;
protected $lotto;
protected $compat_list;
function __construct(array $values) {
$this->code = $values['code'];
$this->image = $values['image'];
$this->color = $values['color'];
$this->barcode = $values['barcode'];
$this->lotto = $values['lotto'];
$this->compat_list = $values['compat_list'];
}
public function getCode() {
return $this->code;
}
function getImg() {
return sprintf('%s/../../data/img/%s', __DIR__, $this->image);
}
public function getColor() {
return $this->color;
}
public function getBarCode() {
return $this->barcode;
}
public function getLotto() {
return $this->lotto;
}
public function getCompatList() {
return $this->compat_list;
}
}
class LabelPDFGenerator {
var $debug = false;
public function __construct($debug=false) {
$this->debug = $debug;
define('K_TCPDF_THROW_EXCEPTION_ERROR', true );
//
ini_set("memory_limit",-1);
set_time_limit(0);
// create new PDF document
$this->P = new \TCPDF(
$orientation=PDF_PAGE_ORIENTATION, $unit='mm', $format='A4', $unicode=true,
$encoding='UTF-8', $diskcache=false, $pdfa=false
);
// remove header and footer
$this->P->setPrintHeader(false);
$this->P->setPrintFooter(false);
// set margins
$this->P->SetMargins($left=0, $top=0, $right=0, $keepmargins=true);
// set auto page breaks false, altrimenti se "lotto" sfora, tcpd lo piazza in una nuova pagina
$this->P->SetAutoPageBreak(false, 0);
// set image
$this->P->setImageScale(PDF_IMAGE_SCALE_RATIO);
$this->P->setJPEGQuality(100);
// set font
$this->P->SetFont('helvetica', '', 8.5);
$this->P->setCellMargins($left = 0, $top = 0, $right = 0, $bottom = 0);
// set default monospaced font
$this->P->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
}
//------------------------------------------------------------------------------
// genera il pdf in memoria, successivamente va chiamata una funzione di output
public function generate(ItemValRecPager $data_pager) {
$x = 0; // orizzontale
$y = 0; // verticale
$idx = 0; // contatore record corrente
$label_num_per_col = (ItemValRecPager::LABEL_NUM_PER_PAGE / 2) -1; // numero di etichette per collonna, meno 1 perché array parte con 0 che indica la prima etichetta
for ($page_i = 0; $page_i < $data_pager->getPagesCount(); $page_i++) {
// add a page
$this->addPage();
$y_label_offset = 57;
$y_range = range(0, $label_num_per_col * $y_label_offset, $y_label_offset); //[10,20,30,40,50]
foreach ($y_range as $y) {
foreach ([10, 115] as $x) { // cicla per la collonna 0 e 110
$this->generateLabel($x, $y, $item=$data_pager->getRecordByIdx($idx));
$idx++;
}
}
}
}
public function saveToFile($file_path) {
// Close and output PDF document to a file
$this->P->Output($file_path, 'F');
}
public function download() {
// Close and output PDF document to a file, I => inline download
$this->P->Output('', 'I');
}
//----------------------------------------------------------------------------
// sub generators
//----------------------------------------------------------------------------
function generateLabel($x, $y, ItemValRec $item = null) {
if (empty($item)) {
return; // no op
}
$x_initial = $x; //conserva posizione di partenza
$y_initial = $y; //conserva posizione di partenza
$this->addText('Art.' . $item->getCode(), $x, $y, ['style' => 'B']);
$this->addText('Set fodere SUPERIOR per / SUPERIOR seat cover for', $x, $y += 3.5);
//
$a_compat = $item->getCompatList();
list($y_compat_label_offset, $compat_label_fontsize) = $this->getCompatListSizeVariant($a_compat);
foreach ($a_compat as $i => $str_compat) {
$label_y = $y + $y_compat_label_offset + ($i * $y_compat_label_offset);
$this->addText($str_compat, $x, $label_y, ['size' => $compat_label_fontsize]);
}
// resetta y per gestire il fatto che il numero di auto compatibili varia da 1 a x
$y = $y + 24;
$this->addText($item->getColor(), $x, $y, ['style' => 'B']);
$this->addBarcode($item->getBarCode(), $x, $y += 15);
$y_before_barcode = $y;
//
$this->addText('Lotto: ' . $item->getLotto(), $x, $y-1.5, ['size' => 6.5]);
// Image example with resizing
$file_name = $item->getImg();
$x_col2 = $x + 42;
// dimensioni immagine
$aspect_ratio = self::getAspectRatio($file_name);
$h = 15;
$w = ($h * $aspect_ratio);
$w = round($w, 3);
//
$this->addImage($file_name, $x_col2, $y_before_barcode, $w, $h);
//
// corner crop marks
$h = $x_initial == 10 ? 0 : 40; //sulla prima colonna corto, altrimenti lungo
//// $this->addCropMark($x - 5, $y_before_barcode + 18, $t = 'TR', $h); // bottom-left mark
}
// da un filename ricava l'aspect ration $w/$h
public static function getAspectRatio($file_name) {
$a_size = getimagesize($file_name);
$w = $a_size[0];
$h = $a_size[1];
if (!empty($w) && !empty($h)) {
return $w / $h;
} else {
return 1;
}
}
// la grandezza del font, e quindi dell'interlinea dipendono da quante compatibilità veicolo sono presenti
// gestisce fino a 8 labels
public function getCompatListSizeVariant(array $a_compat) {
$c = count($a_compat);
if ($c >= 8) {
$y_compat_label_offset = 2.5;
$compat_label_fontsize = 5.5;
} elseif ($c == 7) {
$y_compat_label_offset = 3;
$compat_label_fontsize = 6;
} elseif ($c == 6) {
$y_compat_label_offset = 3.5;
$compat_label_fontsize = 6.5;
} elseif ($c == 5) {
$y_compat_label_offset = 4;
$compat_label_fontsize = 7;
} else { // 4 o meno
$y_compat_label_offset = 5;
$compat_label_fontsize = 8;
}
return [$y_compat_label_offset, $compat_label_fontsize];
}
//----------------------------------------------------------------------------
// utils
//----------------------------------------------------------------------------
function addPage(){
$this->P->AddPage();
if( $this->debug ){
// Display image on full page
$bg_img_path = __DIR__.'/../../public/img/BG.png';
$autocalc=0;// w h auto
$this->P->Image(
$bg_img_path, $x=0, $y=0, $w=210, $h=297, $type='PNG'
,$link='', $align='', $resize=false, $dpi=300, $palign='',
$ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=true,
$alt=false, $altimgs=[]
);
}
}
function addText($txt, $x, $y, array $opt = []) {
$option = array_merge([
'size' => 8.5,
// $style = BI B= bold I=italic
'style' => '',
], $opt);
extract($option);
// set font
$this->P->SetFont($family = 'helvetica', $style, $size);
$this->P->SetXY($x, $y);
$this->P->Cell(
$w = 63.5, $h = 33, $txt, $border = 0, $ln = 0, $align = 'L', $fill = false, $link = '', $stretch = 0, $ignore_min_height = false, $calign = 'C', $valign = 'B'
);
}
function addLongText() {
// print a message
// $txt = "";
// $this->P->MultiCell(70, 50, $txt, 0, 'J', false, 1, 125, 30, true, 0, false, true, 0, 'T', false);
// $this->P->SetY(30);
}
function addBarcode($code, $x, $y, $w = 43, $h = 15) {
$this->P->SetXY($x, $y);
// The width is set to the the same as the cell containing the name.
// The Y position is also adjusted slightly.
// define barcode style
// Reset X,Y so wrapping cell wraps around the barcode's cell.
$style = [
'position' => '',
'align' => 'L',
'stretch' => false,
'fitwidth' => false,
'cellfitalign' => '',
'border' => false,
'hpadding' => 'auto',
'vpadding' => 'auto',
'fgcolor' => [0, 0, 0],
'bgcolor' => false, //[255,255,255],
'text' => true,
'font' => 'helvetica',
'fontsize' => 7,
'stretchtext' => 0,
];
$this->P->write1DBarcode(
$code, $type = 'EAN13', $x, $y, $w, $h, $xres = 0.4, $style, $align = 'L'
);
}
function addImage($file_name, $x, $y, $w, $h) {
$this->P->Image(
$file_name, $x, $y,
$w,
$h,
$type = 'JPG', $link = '',
$align = '', $resize = false, $dpi = 300, $palign = '', $ismask = false,
$imgmask = false, $border = 0, $fitbox = false, $hidden = false, $fitonpage = false,
$alt = false, $altimgs = []
);
}
public function addCropMark($x, $y, $t, $h = 60, $c_gray = [192, 192, 192]) {
$this->P->cropMark($x, $y, $w = 80, $h, $t, $c_gray); // bottom-right mark
}
}
}
//----------------------------------------------------------------------------
// main
//----------------------------------------------------------------------------
namespace {
require_once __DIR__.'/../application/lib/PDFEtichettaFornitori.php';
require_once __DIR__ . '/../vendor/autoload.php';
date_default_timezone_set('Europe/Rome');
// init numero random data da stampare
$num_etichette = (isset($_SERVER['argv'][1])) ? $_SERVER['argv'][1] : rand(1, 24);
$data_pager = new \PDFEtichettaFornitori\ItemValRecPager();
$data_pager->initRandomData($num_etichette);
//
$pdf_gen = new \PDFEtichettaFornitori\LabelPDFGenerator($debug=true );
$pdf_gen->generate($data_pager);
$file_path = __DIR__ . '/barcodes.pdf';
$pdf_gen->saveToFile($file_path);
}
# pacchetti accessori necessari al funzionamento PDF # sudo apt-get install texlive-latex-base # sudo apt-get install texlive-xetex # sudo apt-get install texlive-fonts-recommended # sudo apt-get install texlive-latex-extra # markdown to html pandoc -s \ -H ./manual.css \ --from markdown_phpextra+footnotes+inline_code_attributes+fenced_code_attributes+grid_tables \ --highlight-style kate \ -A ./footer.md \ --to html ./index.md > ./_maual.html
# markdown to PDF pandoc --toc ./index.md --latex-engine=xelatex -o example13.pdf
css @media: print debug