| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | <?php/**	Classe de génération des PDF à partir d'un flux html.	Fonctionne sous linux et windows, necessite les binaires wkhtml placés dans "erp\lib\wkhtmltopdf"	Sous linux :	sudo wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-amd64.tar.xz	sudo tar xvf wkhtmltox-0.12.4_linux-generic-amd64.tar.xz	sudo mv wkhtmltox/bin/wkhtmlto* /usr/bin/	sudo ln -nfs /usr/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf	sudo chmod a+x /usr/local/bin/wkhtmltopdf	sudo apt-get install openssl build-essential xorg libssl-dev	sudo apt-get install xvfb	echo xvfb-run -a -s "-screen 0 640x480x16" wkhtmltopdf "$@" > /usr/local/bin/wkhtmltopdf.sh	sudo chmod a+x /usr/local/bin/wkhtmltopdf.sh	ex utilisation :	$pdf = new Pdf('<h1>Hello World</h1>');	$pdf->orientation = 'Landscape';	header('Content-Type: application/pdf');	header('Content-Disposition: attachment; filename="my.pdf"');	echo $pdf->generate();	Pour ajouter un header, il faut ajouter les éléments suivants :	<!-- #header --> avant le contenu du header	<!-- /header --> après le contenu du header	De même avec le footer (remplacer header par footer)	@author v.carruesco, v.morreel	@version 2.0**/class Pdf{	public $html,$orientation,$margin,$css;	function __construct($html=null, $margin=array(), $format='A4', $orientation='Portrait'){		$this->html = $html;		$this->margin = (object) array(			'top' => isset($margin['top']) ? $margin['top'] : '10',			'right' => isset($margin['right']) ? $margin['right'] : '10',			'bottom' => isset($margin['bottom']) ? $margin['bottom'] : '10',			'left' => isset($margin['left']) ? $margin['left'] : '10'		);		$this->format = $format;		$this->orientation = $orientation;	}	// Retourne (uniquement sur les pdf avec texte editable) la liste des champs editable	// du pdf spécifié et leurs valeurs. Si le parametre onlyfdf est a true, la méthode retournera	// le format fdf brut (utile uniquement pour du débug ou pour de l'interne)	// NB : Penser a installer ``apt-get install pdftk`` (ou pdftk pour windows) sur le système avant de lancer ce script	public static function extractData($file,$onlyfdf = false){		$command = 'pdftk '.$file.' generate_fdf output -';		$datastream = shell_exec($command);		if($onlyfdf) return $datastream;		preg_match_all('|\/V ([^\n]*)\n\/T \(([^\n]*)\)|iUsm', $datastream, $matches,PREG_SET_ORDER);		$parameters = array();		foreach ($matches as $match) {			if(count($match)==3)			$parameters[$match[2]] = $match[1];		}		return $parameters;	}	// Utilise le pdf $file comme modèle (uniquement un pdf avec texte editable) et le remplis avec le tableau clé valeur $parameters	// puis retourne le flux du pdf remplis.	// Mettre la valeur /Yes pour les checkbox cochées ou / pour les décochées	// L'argument $flat, définit si le document final doit être a plat ou encore editable	// NB : Penser a installer ``apt-get install pdftk`` (ou pdftk pour windows) sur le système avant de lancer ce script	public static function fillData($file,$parameters,$flat = false){		$fdf = self::extractData($file,true);		$fdf = preg_replace_callback('|\/V ([^\n]*)\n\/T \(([^\n]*)\)|ism',function($m) use ($parameters){			$return = '/V ';			$value = isset($parameters[$m[2]]) ? $parameters[$m[2]]: '';			if($value=='/'){				$return .= $value;			}else{				$return .= '('.$value.')';			}			$return .= PHP_EOL;			$return .= '/T ('.$m[2].')';			return $return;		},$fdf);		//$command = 'echo "'.str_replace('"','\"',$fdf).'"| pdftk '.$file.' fill_form - output -';		$fdfPath = File::temp().rand(0,10000).'fdf';		$pdfPath = File::temp().rand(0,10000).'pdf';		file_put_contents($fdfPath, $fdf);		$command = 'pdftk '.$file.' fill_form '.$fdfPath.' output "'.$pdfPath.'"';		if($flat) $command.=' flatten';		shell_exec($command);		$datastream = file_get_contents($pdfPath);		unlink($pdfPath);		unlink($fdfPath);		return $datastream;	}	/*	Convertis le tableau de chemin d'images fournis en un PDF	Prérequis systeme :	- Installer le paquet imagemagick (apt-get install imagemagick)	nb: Si le pb "convert-im6.q16: not authorized `outfile.pdf' @ error/constitute.c/WriteImage/1037" apparait	editer /etc/ImageMagick-6/policy.xml et changer sur la ligne "<policy domain="coder" rights="none" pattern="PDF" />" PDF le droit none à read|write .*/	public static function fromImage($images,$pdfPath){		return Image::toPdf($images,$pdfPath);	}	public function generate($alt = false){		$fileName = time().mt_rand(0,100);		if(!file_exists(File::dir().'tmp')) mkdir(File::dir().'tmp');		$bodyPath = File::dir().'tmp'.SLASH.$fileName.'.html';		$pdfPath = File::dir().'tmp'.SLASH.$fileName.'.pdf';		$body = $this->html;		$head = '';		$foot = '';		if($alt) {			//Récupération des actions URL html	        if(preg_match_all("/url\((\'|\")(.*)(\"|\')/U", $body, $match)) {	        	$urls = $match[2];	        	foreach ($urls as $key => $url) {	        		if (preg_match("/asset=(.*.woff(2?))/i", $url, $asset)) {						$path = get_asset_absolute_path($asset[1]);	        			$body = str_replace($url, $path, $body);	        		}	        	}	        }		}		//Récupération du head html        if(preg_match("/<!DOCTYPE.*<body.*>/isU", $body, $match))        	$head = $match[0];        //Récupération du footer html        if(preg_match("/<\/body>.*<\/html>/isU", $body, $match))        	$foot = $match[0];		//Récupération du header pdf        if(preg_match("/<!--[\s\t\r\n]*#header[\s\t\r\n]*-->(.*)<!--[\s\t\r\n]*\/header[\s\t\r\n]*-->/isU", $body, $match))        	$header = $match[0];        //Récupération du footer pdf        if(preg_match("/<!--[\s\t\r\n]*#footer[\s\t\r\n]*-->(.*)<!--[\s\t\r\n]*\/footer[\s\t\r\n]*-->/isU", $body, $match))        	$footer = $match[0];        //Récupération du body        if(isset($header)){        	$body = str_replace($header, '', $body);        	$header = $head.$header.$foot;        }        if(isset($footer)){        	$body = str_replace($footer, '', $body);        	$footer = $head.$footer.$foot;        }		file_put_contents($bodyPath, $body);		$outcmd = array();		$cmd = get_OS() === 'WIN' ? '"C:'.SLASH.'Program Files'.SLASH.'wkhtmltopdf'.SLASH.'bin'.SLASH.'wkhtmltopdf.exe" ' : "/usr/local/bin/wkhtmltopdf.sh ";		$cmd .= '-s '.$this->format.' -O '.$this->orientation.' -T '.$this->margin->top.' -R '.$this->margin->right.' -B '.$this->margin->bottom.' -L '.$this->margin->left;		$cmd .= ' -d 100 --print-media-type ';		$cmd .= ' --user-style-sheet '.dirname(__FILE__).'/../'.$this->css.' --enable-javascript --javascript-delay 1000 ';		if(isset($header)) {			$headerPath = File::dir().'tmp'.SLASH.'header-'.$fileName.'.html';			file_put_contents($headerPath, $header);			$cmd .= ' --header-html '.$headerPath.' --header-spacing 5';		}		if(isset($footer)) {			$footerPath = File::dir().'tmp'.SLASH.'footer-'.$fileName.'.html';			file_put_contents($footerPath, $footer);			$cmd .= ' --footer-html '.$footerPath.' --footer-spacing 5';		}		$cmd .= ' --footer-right "[page] / [toPage]" --footer-font-size 8 ';		$cmd .= $bodyPath.' '.$pdfPath;		exec($cmd, $outcmd);		$stream = file_get_contents($pdfPath);		if(isset($header)) unlink($headerPath);		if(isset($footer)) unlink($footerPath);		unlink($bodyPath);		unlink($pdfPath);		return $stream;	}}?>
 |