First commit
This commit is contained in:
commit
c6e2478c40
13918 changed files with 2303184 additions and 0 deletions
232
sites/all/modules/civicrm/CRM/Utils/PDF/Document.php
Normal file
232
sites/all/modules/civicrm/CRM/Utils/PDF/Document.php
Normal file
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
|
||||
require_once 'TbsZip/tbszip.php';
|
||||
|
||||
/**
|
||||
* Class CRM_Utils_PDF_Document.
|
||||
*/
|
||||
class CRM_Utils_PDF_Document {
|
||||
|
||||
public static $ooxmlMap = array(
|
||||
'docx' => array(
|
||||
'dataFile' => 'word/document.xml',
|
||||
'startTag' => '<w:body>',
|
||||
'pageBreak' => '<w:p><w:pPr><w:pStyle w:val="Normal"/><w:rPr></w:rPr></w:pPr><w:r><w:rPr></w:rPr></w:r><w:r><w:br w:type="page"/></w:r></w:p>',
|
||||
'endTag' => '</w:body></w:document>',
|
||||
),
|
||||
'odt' => array(
|
||||
'dataFile' => 'content.xml',
|
||||
'startTag' => '<office:body>',
|
||||
'pageBreak' => '<text:p text:style-name="Standard"></text:p>',
|
||||
'endTag' => '</office:body></office:document-content>',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Convert html to a Doc file.
|
||||
*
|
||||
* @param array $pages
|
||||
* List of HTML snippets.
|
||||
* @param string $fileName
|
||||
* The logical filename to return to client.
|
||||
* Ex: "HelloWorld.odt".
|
||||
* @param array|int $format
|
||||
*/
|
||||
public static function html2doc($pages, $fileName, $format = array()) {
|
||||
if (is_array($format)) {
|
||||
// PDF Page Format parameters passed in - merge with defaults
|
||||
$format += CRM_Core_BAO_PdfFormat::getDefaultValues();
|
||||
}
|
||||
else {
|
||||
// PDF Page Format ID passed in
|
||||
$format = CRM_Core_BAO_PdfFormat::getById($format);
|
||||
}
|
||||
$paperSize = CRM_Core_BAO_PaperSize::getByName($format['paper_size']);
|
||||
|
||||
$metric = CRM_Core_BAO_PdfFormat::getValue('metric', $format);
|
||||
$pageStyle = array(
|
||||
'orientation' => CRM_Core_BAO_PdfFormat::getValue('orientation', $format),
|
||||
'pageSizeW' => self::toTwip($paperSize['width'], $paperSize['metric']),
|
||||
'pageSizeH' => self::toTwip($paperSize['height'], $paperSize['metric']),
|
||||
'marginTop' => self::toTwip(CRM_Core_BAO_PdfFormat::getValue('margin_top', $format), $metric),
|
||||
'marginRight' => self::toTwip(CRM_Core_BAO_PdfFormat::getValue('margin_right', $format), $metric),
|
||||
'marginBottom' => self::toTwip(CRM_Core_BAO_PdfFormat::getValue('margin_bottom', $format), $metric),
|
||||
'marginLeft' => self::toTwip(CRM_Core_BAO_PdfFormat::getValue('margin_left', $format), $metric),
|
||||
);
|
||||
|
||||
$ext = pathinfo($fileName, PATHINFO_EXTENSION);
|
||||
|
||||
$phpWord = new \PhpOffice\PhpWord\PhpWord();
|
||||
|
||||
$phpWord->getDocInfo()
|
||||
->setCreator(CRM_Core_DAO::getFieldValue('CRM_Contact_BAO_Contact', CRM_Core_Session::getLoggedInContactID(), 'display_name'));
|
||||
|
||||
foreach ((array) $pages as $page => $html) {
|
||||
$section = $phpWord->addSection($pageStyle + array('breakType' => 'nextPage'));
|
||||
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $html);
|
||||
}
|
||||
|
||||
self::printDoc($phpWord, $ext, $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object|string $phpWord
|
||||
* @param string $ext
|
||||
* File extension/type.
|
||||
* Ex: docx, odt, html.
|
||||
* @param string $fileName
|
||||
* The logical filename to return to client.
|
||||
* Ex: "HelloWorld.odt".
|
||||
* Alternatively, a full path of a file to display. This seems sketchy.
|
||||
* Ex: "/var/lib/data/HelloWorld.odt".
|
||||
*/
|
||||
public static function printDoc($phpWord, $ext, $fileName) {
|
||||
$formats = array(
|
||||
'docx' => 'Word2007',
|
||||
'odt' => 'ODText',
|
||||
'html' => 'HTML',
|
||||
// todo
|
||||
'pdf' => 'PDF',
|
||||
);
|
||||
|
||||
if (realpath($fileName)) {
|
||||
$phpWord = \PhpOffice\PhpWord\IOFactory::load($fileName, $formats[$ext]);
|
||||
}
|
||||
|
||||
\PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(TRUE); //CRM-20015
|
||||
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, $formats[$ext]);
|
||||
|
||||
CRM_Utils_System::setHttpHeader('Content-Type', "application/$ext");
|
||||
CRM_Utils_System::setHttpHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"');
|
||||
$objWriter->save("php://output");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $metric
|
||||
* @return int
|
||||
*/
|
||||
public static function toTwip($value, $metric) {
|
||||
$point = CRM_Utils_PDF_Utils::convertMetric($value, $metric, 'pt');
|
||||
return \PhpOffice\PhpWord\Shared\Converter::pointToTwip($point);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $path docx/odt file path
|
||||
* @param string $type File type
|
||||
*
|
||||
* @return array
|
||||
* Return extracted content of document in HTML and document type
|
||||
*/
|
||||
public static function docReader($path, $type) {
|
||||
$type = array_search($type, CRM_Core_SelectValues::documentApplicationType());
|
||||
$fileType = ($type == 'docx') ? 'Word2007' : 'ODText';
|
||||
|
||||
$phpWord = \PhpOffice\PhpWord\IOFactory::load($path, $fileType);
|
||||
$phpWordHTML = new \PhpOffice\PhpWord\Writer\HTML($phpWord);
|
||||
|
||||
// return the html content for tokenreplacment and eventually used for document download
|
||||
return array($phpWordHTML->getWriterPart('Body')->write(), $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract content of docx/odt file
|
||||
*
|
||||
* @param string $filePath Document file path
|
||||
* @param string $docType File type of document
|
||||
*
|
||||
* @return array
|
||||
* [string, clsTbsZip]
|
||||
*/
|
||||
public static function unzipDoc($filePath, $docType) {
|
||||
$dataFile = self::$ooxmlMap[$docType]['dataFile'];
|
||||
|
||||
$zip = new clsTbsZip();
|
||||
$zip->Open($filePath);
|
||||
$content = $zip->FileRead($dataFile);
|
||||
|
||||
return array($content, $zip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify contents of docx/odt file(s) and later merged into one final document
|
||||
*
|
||||
* @param array $contents
|
||||
* Content of formatted/token-replaced document.
|
||||
* List of HTML snippets.
|
||||
* @param string $fileName
|
||||
* The logical filename to return to client.
|
||||
* Ex: "HelloWorld.odt".
|
||||
* @param string $docType
|
||||
* Document type e.g. odt/docx
|
||||
* @param clsTbsZip $zip
|
||||
* Zip archive
|
||||
* @param bool $returnFinalContent
|
||||
* Return the content of file document as a string used in unit test
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function printDocuments($contents, $fileName, $docType, $zip, $returnFinalContent = FALSE) {
|
||||
$dataMap = self::$ooxmlMap[$docType];
|
||||
|
||||
$finalContent = $zip->FileRead($dataMap['dataFile']);
|
||||
|
||||
// token-replaced document contents of each contact will be merged into final document
|
||||
foreach ($contents as $key => $content) {
|
||||
if ($key == 0) {
|
||||
$finalContent = $content;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 1. fetch the start position of document body
|
||||
// 2. later fetch only the body part starting from position $start
|
||||
// 3. replace closing body tag with pageBreak
|
||||
// 4. append the $content to the finalContent
|
||||
$start = strpos($content, $dataMap['startTag']);
|
||||
$content = substr($content, $start);
|
||||
$content = str_replace($dataMap['startTag'], $dataMap['pageBreak'], $content);
|
||||
$finalContent = str_replace($dataMap['endTag'], $content, $finalContent);
|
||||
}
|
||||
|
||||
if ($returnFinalContent) {
|
||||
return $finalContent;
|
||||
}
|
||||
|
||||
// Replace the loaded document file content located at $filePath with $finaContent
|
||||
$zip->FileReplace($dataMap['dataFile'], $finalContent, TBSZIP_STRING);
|
||||
|
||||
$zip->Flush(TBSZIP_DOWNLOAD, $fileName);
|
||||
}
|
||||
|
||||
}
|
290
sites/all/modules/civicrm/CRM/Utils/PDF/Label.php
Normal file
290
sites/all/modules/civicrm/CRM/Utils/PDF/Label.php
Normal file
|
@ -0,0 +1,290 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class to print labels in Avery or custom formats
|
||||
* functionality and smarts to the base PDF_Label.
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class CRM_Utils_PDF_Label
|
||||
*/
|
||||
class CRM_Utils_PDF_Label extends TCPDF {
|
||||
|
||||
// make these properties public due to
|
||||
// CRM-5880
|
||||
// Default label format values
|
||||
public $defaults;
|
||||
// Current label format values
|
||||
public $format;
|
||||
// Name of format
|
||||
public $formatName;
|
||||
// Left margin of labels
|
||||
public $marginLeft;
|
||||
// Top margin of labels
|
||||
public $marginTop;
|
||||
// Horizontal space between 2 labels
|
||||
public $xSpace;
|
||||
// Vertical space between 2 labels
|
||||
public $ySpace;
|
||||
// Number of labels horizontally
|
||||
public $xNumber;
|
||||
// Number of labels vertically
|
||||
public $yNumber;
|
||||
// Width of label
|
||||
public $width;
|
||||
// Height of label
|
||||
public $height;
|
||||
// Line Height of label - used in event code
|
||||
public $lineHeight = 0;
|
||||
// Space between text and left edge of label
|
||||
public $paddingLeft;
|
||||
// Space between text and top edge of label
|
||||
public $paddingTop;
|
||||
// Character size (in points)
|
||||
public $charSize;
|
||||
// Metric used for all PDF doc measurements
|
||||
public $metricDoc;
|
||||
// Name of the font
|
||||
public $fontName;
|
||||
// 'B' bold, 'I' italic, 'BI' bold+italic
|
||||
public $fontStyle;
|
||||
// Paper size name
|
||||
public $paperSize;
|
||||
// Paper orientation
|
||||
public $orientation;
|
||||
// Paper dimensions array (w, h)
|
||||
public $paper_dimensions;
|
||||
// Counter for positioning labels
|
||||
public $countX = 0;
|
||||
// Counter for positioning labels
|
||||
public $countY = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param $format
|
||||
* Either the name of a Label Format in the Option Value table.
|
||||
* or an array of Label Format values.
|
||||
* @param string|\Unit $unit Unit of measure for the PDF document
|
||||
*/
|
||||
public function __construct($format, $unit = 'mm') {
|
||||
if (is_array($format)) {
|
||||
// Custom format
|
||||
$tFormat = $format;
|
||||
}
|
||||
else {
|
||||
// Saved format
|
||||
$tFormat = CRM_Core_BAO_LabelFormat::getByName($format);
|
||||
}
|
||||
|
||||
$this->LabelSetFormat($tFormat, $unit);
|
||||
parent::__construct($this->orientation, $this->metricDoc, $this->paper_dimensions);
|
||||
$this->generatorMethod = NULL;
|
||||
$this->SetFont($this->fontName, $this->fontStyle);
|
||||
$this->SetFontSize($this->charSize);
|
||||
$this->SetMargins(0, 0);
|
||||
$this->SetAutoPageBreak(FALSE);
|
||||
$this->setPrintHeader(FALSE);
|
||||
$this->setPrintFooter(FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $objectinstance
|
||||
* @param string $methodname
|
||||
*/
|
||||
public function SetGenerator($objectinstance, $methodname = 'generateLabel') {
|
||||
$this->generatorMethod = $methodname;
|
||||
$this->generatorObject = $objectinstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param bool $convert
|
||||
*
|
||||
* @return float|int|mixed
|
||||
*/
|
||||
public function getFormatValue($name, $convert = FALSE) {
|
||||
if (isset($this->format[$name])) {
|
||||
$value = $this->format[$name];
|
||||
$metric = $this->format['metric'];
|
||||
}
|
||||
else {
|
||||
$value = CRM_Utils_Array::value($name, $this->defaults);
|
||||
$metric = $this->defaults['metric'];
|
||||
}
|
||||
if ($convert) {
|
||||
$value = CRM_Utils_PDF_Utils::convertMetric($value, $metric, $this->metricDoc);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize label format settings.
|
||||
*
|
||||
* @param $format
|
||||
* @param $unit
|
||||
*/
|
||||
public function LabelSetFormat(&$format, $unit) {
|
||||
$this->defaults = CRM_Core_BAO_LabelFormat::getDefaultValues();
|
||||
$this->format = &$format;
|
||||
$this->formatName = $this->getFormatValue('name');
|
||||
$this->paperSize = $this->getFormatValue('paper-size');
|
||||
$this->orientation = $this->getFormatValue('orientation');
|
||||
$this->fontName = $this->getFormatValue('font-name');
|
||||
$this->charSize = $this->getFormatValue('font-size');
|
||||
$this->fontStyle = $this->getFormatValue('font-style');
|
||||
$this->xNumber = $this->getFormatValue('NX');
|
||||
$this->yNumber = $this->getFormatValue('NY');
|
||||
$this->metricDoc = $unit;
|
||||
$this->marginLeft = $this->getFormatValue('lMargin', TRUE);
|
||||
$this->marginTop = $this->getFormatValue('tMargin', TRUE);
|
||||
$this->xSpace = $this->getFormatValue('SpaceX', TRUE);
|
||||
$this->ySpace = $this->getFormatValue('SpaceY', TRUE);
|
||||
$this->width = $this->getFormatValue('width', TRUE);
|
||||
$this->height = $this->getFormatValue('height', TRUE);
|
||||
$this->paddingLeft = $this->getFormatValue('lPadding', TRUE);
|
||||
$this->paddingTop = $this->getFormatValue('tPadding', TRUE);
|
||||
$paperSize = CRM_Core_BAO_PaperSize::getByName($this->paperSize);
|
||||
$w = CRM_Utils_PDF_Utils::convertMetric($paperSize['width'], $paperSize['metric'], $this->metricDoc);
|
||||
$h = CRM_Utils_PDF_Utils::convertMetric($paperSize['height'], $paperSize['metric'], $this->metricDoc);
|
||||
$this->paper_dimensions = array($w, $h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the pdf of one label (can be modified using SetGenerator)
|
||||
*
|
||||
* @param string $text
|
||||
*/
|
||||
public function generateLabel($text) {
|
||||
$args = array(
|
||||
'w' => $this->width,
|
||||
'h' => 0,
|
||||
'txt' => $text,
|
||||
'border' => 0,
|
||||
'align' => 'L',
|
||||
'fill' => 0,
|
||||
'ln' => 0,
|
||||
'x' => '',
|
||||
'y' => '',
|
||||
'reseth' => TRUE,
|
||||
'stretch' => 0,
|
||||
'ishtml' => FALSE,
|
||||
'autopadding' => FALSE,
|
||||
'maxh' => $this->height,
|
||||
);
|
||||
|
||||
CRM_Utils_Hook::alterMailingLabelParams($args);
|
||||
|
||||
if ($args['ishtml'] == TRUE) {
|
||||
$this->writeHTMLCell($args['w'], $args['h'],
|
||||
$args['x'], $args['y'],
|
||||
$args['txt'], $args['border'],
|
||||
$args['ln'], $args['fill'],
|
||||
$args['reseth'], $args['align'],
|
||||
$args['autopadding']
|
||||
);
|
||||
}
|
||||
else {
|
||||
$this->multiCell($args['w'], $args['h'],
|
||||
$args['txt'], $args['border'],
|
||||
$args['align'], $args['fill'],
|
||||
$args['ln'], $args['x'],
|
||||
$args['y'], $args['reseth'],
|
||||
$args['stretch'], $args['ishtml'],
|
||||
$args['autopadding'], $args['maxh']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a label.
|
||||
*
|
||||
* @param $texte
|
||||
*/
|
||||
public function AddPdfLabel($texte) {
|
||||
if ($this->countX == $this->xNumber) {
|
||||
// Page full, we start a new one
|
||||
$this->AddPage();
|
||||
$this->countX = 0;
|
||||
$this->countY = 0;
|
||||
}
|
||||
|
||||
$posX = $this->marginLeft + ($this->countX * ($this->width + $this->xSpace));
|
||||
$posY = $this->marginTop + ($this->countY * ($this->height + $this->ySpace));
|
||||
$this->SetXY($posX + $this->paddingLeft, $posY + $this->paddingTop);
|
||||
if ($this->generatorMethod) {
|
||||
call_user_func_array(array($this->generatorObject, $this->generatorMethod), array($texte));
|
||||
}
|
||||
else {
|
||||
$this->generateLabel($texte);
|
||||
}
|
||||
$this->countY++;
|
||||
|
||||
if ($this->countY == $this->yNumber) {
|
||||
// End of column reached, we start a new one
|
||||
$this->countX++;
|
||||
$this->countY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available font names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFontNames() {
|
||||
// Define labels for TCPDF core fonts
|
||||
$fontLabel = array(
|
||||
'courier' => ts('Courier'),
|
||||
'helvetica' => ts('Helvetica'),
|
||||
'times' => ts('Times New Roman'),
|
||||
'dejavusans' => ts('Deja Vu Sans (UTF-8)'),
|
||||
);
|
||||
|
||||
// Check to see if we have any additional fonts to add. You can specify more fonts in
|
||||
// civicrm.settings.php via: $config['CiviCRM Preferences']['additional_fonts']
|
||||
// CRM-13307
|
||||
$additionalFonts = Civi::settings()->get('additional_fonts');
|
||||
if (is_array($additionalFonts)) {
|
||||
$fontLabel = array_merge($fontLabel, $additionalFonts);
|
||||
}
|
||||
|
||||
$tcpdfFonts = $this->fontlist;
|
||||
foreach ($tcpdfFonts as $fontName) {
|
||||
if (array_key_exists($fontName, $fontLabel)) {
|
||||
$list[$fontName] = $fontLabel[$fontName];
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
}
|
320
sites/all/modules/civicrm/CRM/Utils/PDF/Utils.php
Normal file
320
sites/all/modules/civicrm/CRM/Utils/PDF/Utils.php
Normal file
|
@ -0,0 +1,320 @@
|
|||
<?php
|
||||
/*
|
||||
+--------------------------------------------------------------------+
|
||||
| CiviCRM version 4.7 |
|
||||
+--------------------------------------------------------------------+
|
||||
| Copyright CiviCRM LLC (c) 2004-2017 |
|
||||
+--------------------------------------------------------------------+
|
||||
| This file is a part of CiviCRM. |
|
||||
| |
|
||||
| CiviCRM is free software; you can copy, modify, and distribute it |
|
||||
| under the terms of the GNU Affero General Public License |
|
||||
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
|
||||
| |
|
||||
| CiviCRM is distributed in the hope that it will be useful, but |
|
||||
| WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|
||||
| See the GNU Affero General Public License for more details. |
|
||||
| |
|
||||
| You should have received a copy of the GNU Affero General Public |
|
||||
| License and the CiviCRM Licensing Exception along |
|
||||
| with this program; if not, contact CiviCRM LLC |
|
||||
| at info[AT]civicrm[DOT]org. If you have questions about the |
|
||||
| GNU Affero General Public License or the licensing of CiviCRM, |
|
||||
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
|
||||
+--------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
/**
|
||||
*
|
||||
* @package CRM
|
||||
* @copyright CiviCRM LLC (c) 2004-2017
|
||||
*/
|
||||
class CRM_Utils_PDF_Utils {
|
||||
|
||||
/**
|
||||
* @param array $text
|
||||
* List of HTML snippets.
|
||||
* @param string $fileName
|
||||
* The logical filename to display.
|
||||
* Ex: "HelloWorld.pdf".
|
||||
* @param bool $output
|
||||
* FALSE to display PDF. TRUE to return as string.
|
||||
* @param null $pdfFormat
|
||||
* Unclear. Possibly PdfFormat or formValues.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public static function html2pdf(&$text, $fileName = 'civicrm.pdf', $output = FALSE, $pdfFormat = NULL) {
|
||||
if (is_array($text)) {
|
||||
$pages = &$text;
|
||||
}
|
||||
else {
|
||||
$pages = array($text);
|
||||
}
|
||||
// Get PDF Page Format
|
||||
$format = CRM_Core_BAO_PdfFormat::getDefaultValues();
|
||||
if (is_array($pdfFormat)) {
|
||||
// PDF Page Format parameters passed in
|
||||
$format = array_merge($format, $pdfFormat);
|
||||
}
|
||||
else {
|
||||
// PDF Page Format ID passed in
|
||||
$format = CRM_Core_BAO_PdfFormat::getById($pdfFormat);
|
||||
}
|
||||
$paperSize = CRM_Core_BAO_PaperSize::getByName($format['paper_size']);
|
||||
$paper_width = self::convertMetric($paperSize['width'], $paperSize['metric'], 'pt');
|
||||
$paper_height = self::convertMetric($paperSize['height'], $paperSize['metric'], 'pt');
|
||||
// dompdf requires dimensions in points
|
||||
$paper_size = array(0, 0, $paper_width, $paper_height);
|
||||
$orientation = CRM_Core_BAO_PdfFormat::getValue('orientation', $format);
|
||||
$metric = CRM_Core_BAO_PdfFormat::getValue('metric', $format);
|
||||
$t = CRM_Core_BAO_PdfFormat::getValue('margin_top', $format);
|
||||
$r = CRM_Core_BAO_PdfFormat::getValue('margin_right', $format);
|
||||
$b = CRM_Core_BAO_PdfFormat::getValue('margin_bottom', $format);
|
||||
$l = CRM_Core_BAO_PdfFormat::getValue('margin_left', $format);
|
||||
|
||||
$stationery_path_partial = CRM_Core_BAO_PdfFormat::getValue('stationery', $format);
|
||||
|
||||
$stationery_path = NULL;
|
||||
if (strlen($stationery_path_partial)) {
|
||||
$doc_root = $_SERVER['DOCUMENT_ROOT'];
|
||||
$stationery_path = $doc_root . "/" . $stationery_path_partial;
|
||||
}
|
||||
|
||||
$margins = array($metric, $t, $r, $b, $l);
|
||||
|
||||
$config = CRM_Core_Config::singleton();
|
||||
|
||||
// Add a special region for the HTML header of PDF files:
|
||||
$pdfHeaderRegion = CRM_Core_Region::instance('export-document-header', FALSE);
|
||||
$htmlHeader = ($pdfHeaderRegion) ? $pdfHeaderRegion->render('', FALSE) : '';
|
||||
|
||||
$html = "
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>
|
||||
<style>@page { margin: {$t}{$metric} {$r}{$metric} {$b}{$metric} {$l}{$metric}; }</style>
|
||||
<style type=\"text/css\">@import url({$config->userFrameworkResourceURL}css/print.css);</style>
|
||||
{$htmlHeader}
|
||||
</head>
|
||||
<body>
|
||||
<div id=\"crm-container\">\n";
|
||||
|
||||
// Strip <html>, <header>, and <body> tags from each page
|
||||
$htmlElementstoStrip = array(
|
||||
'@<head[^>]*?>.*?</head>@siu',
|
||||
'@<script[^>]*?>.*?</script>@siu',
|
||||
'@<body>@siu',
|
||||
'@</body>@siu',
|
||||
'@<html[^>]*?>@siu',
|
||||
'@</html>@siu',
|
||||
'@<!DOCTYPE[^>]*?>@siu',
|
||||
);
|
||||
$htmlElementsInstead = array('', '', '', '', '', '');
|
||||
foreach ($pages as & $page) {
|
||||
$page = preg_replace($htmlElementstoStrip,
|
||||
$htmlElementsInstead,
|
||||
$page
|
||||
);
|
||||
}
|
||||
// Glue the pages together
|
||||
$html .= implode("\n<div style=\"page-break-after: always\"></div>\n", $pages);
|
||||
$html .= "
|
||||
</div>
|
||||
</body>
|
||||
</html>";
|
||||
if ($config->wkhtmltopdfPath) {
|
||||
return self::_html2pdf_wkhtmltopdf($paper_size, $orientation, $margins, $html, $output, $fileName);
|
||||
}
|
||||
else {
|
||||
return self::_html2pdf_dompdf($paper_size, $orientation, $html, $output, $fileName);
|
||||
//return self::_html2pdf_tcpdf($paper_size, $orientation, $margins, $html, $output, $fileName, $stationery_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert html to tcpdf.
|
||||
*
|
||||
* @param $paper_size
|
||||
* @param $orientation
|
||||
* @param $margins
|
||||
* @param $html
|
||||
* @param $output
|
||||
* @param $fileName
|
||||
* @param $stationery_path
|
||||
*/
|
||||
public static function _html2pdf_tcpdf($paper_size, $orientation, $margins, $html, $output, $fileName, $stationery_path) {
|
||||
// Documentation on the TCPDF library can be found at: http://www.tcpdf.org
|
||||
// This function also uses the FPDI library documented at: http://www.setasign.com/products/fpdi/about/
|
||||
// Syntax borrowed from https://github.com/jake-mw/CDNTaxReceipts/blob/master/cdntaxreceipts.functions.inc
|
||||
require_once 'tcpdf/tcpdf.php';
|
||||
require_once 'FPDI/fpdi.php'; // This library is only in the 'packages' area as of version 4.5
|
||||
|
||||
$paper_size_arr = array($paper_size[2], $paper_size[3]);
|
||||
|
||||
$pdf = new TCPDF($orientation, 'pt', $paper_size_arr);
|
||||
$pdf->Open();
|
||||
|
||||
if (is_readable($stationery_path)) {
|
||||
$pdf->SetStationery($stationery_path);
|
||||
}
|
||||
|
||||
$pdf->SetAuthor('');
|
||||
$pdf->SetKeywords('CiviCRM.org');
|
||||
$pdf->setPageUnit($margins[0]);
|
||||
$pdf->SetMargins($margins[4], $margins[1], $margins[2], TRUE);
|
||||
|
||||
$pdf->setJPEGQuality('100');
|
||||
$pdf->SetAutoPageBreak(TRUE, $margins[3]);
|
||||
|
||||
$pdf->AddPage();
|
||||
|
||||
$ln = TRUE;
|
||||
$fill = FALSE;
|
||||
$reset_parm = FALSE;
|
||||
$cell = FALSE;
|
||||
$align = '';
|
||||
|
||||
// output the HTML content
|
||||
$pdf->writeHTML($html, $ln, $fill, $reset_parm, $cell, $align);
|
||||
|
||||
// reset pointer to the last page
|
||||
$pdf->lastPage();
|
||||
|
||||
// close and output the PDF
|
||||
$pdf->Close();
|
||||
$pdf_file = 'CiviLetter' . '.pdf';
|
||||
$pdf->Output($pdf_file, 'D');
|
||||
CRM_Utils_System::civiExit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $paper_size
|
||||
* @param $orientation
|
||||
* @param $html
|
||||
* @param $output
|
||||
* @param string $fileName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function _html2pdf_dompdf($paper_size, $orientation, $html, $output, $fileName) {
|
||||
// CRM-12165 - Remote file support required for image handling.
|
||||
$options = new Options();
|
||||
$options->set('isRemoteEnabled', TRUE);
|
||||
|
||||
$dompdf = new DOMPDF($options);
|
||||
$dompdf->set_paper($paper_size, $orientation);
|
||||
$dompdf->load_html($html);
|
||||
$dompdf->render();
|
||||
|
||||
if ($output) {
|
||||
return $dompdf->output();
|
||||
}
|
||||
else {
|
||||
// CRM-19183 remove .pdf extension from filename
|
||||
$fileName = basename($fileName, ".pdf");
|
||||
$dompdf->stream($fileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $paper_size
|
||||
* @param $orientation
|
||||
* @param $margins
|
||||
* @param $html
|
||||
* @param $output
|
||||
* @param string $fileName
|
||||
*/
|
||||
public static function _html2pdf_wkhtmltopdf($paper_size, $orientation, $margins, $html, $output, $fileName) {
|
||||
require_once 'packages/snappy/src/autoload.php';
|
||||
$config = CRM_Core_Config::singleton();
|
||||
$snappy = new Knp\Snappy\Pdf($config->wkhtmltopdfPath);
|
||||
$snappy->setOption("page-width", $paper_size[2] . "pt");
|
||||
$snappy->setOption("page-height", $paper_size[3] . "pt");
|
||||
$snappy->setOption("orientation", $orientation);
|
||||
$snappy->setOption("margin-top", $margins[1] . $margins[0]);
|
||||
$snappy->setOption("margin-right", $margins[2] . $margins[0]);
|
||||
$snappy->setOption("margin-bottom", $margins[3] . $margins[0]);
|
||||
$snappy->setOption("margin-left", $margins[4] . $margins[0]);
|
||||
$pdf = $snappy->getOutputFromHtml($html);
|
||||
if ($output) {
|
||||
return $pdf;
|
||||
}
|
||||
else {
|
||||
CRM_Utils_System::setHttpHeader('Content-Type', 'application/pdf');
|
||||
CRM_Utils_System::setHttpHeader('Content-Disposition', 'attachment; filename="' . $fileName . '"');
|
||||
echo $pdf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* convert value from one metric to another.
|
||||
*
|
||||
* @param $value
|
||||
* @param $from
|
||||
* @param $to
|
||||
* @param null $precision
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
public static function convertMetric($value, $from, $to, $precision = NULL) {
|
||||
switch ($from . $to) {
|
||||
case 'incm':
|
||||
$value *= 2.54;
|
||||
break;
|
||||
|
||||
case 'inmm':
|
||||
$value *= 25.4;
|
||||
break;
|
||||
|
||||
case 'inpt':
|
||||
$value *= 72;
|
||||
break;
|
||||
|
||||
case 'cmin':
|
||||
$value /= 2.54;
|
||||
break;
|
||||
|
||||
case 'cmmm':
|
||||
$value *= 10;
|
||||
break;
|
||||
|
||||
case 'cmpt':
|
||||
$value *= 72 / 2.54;
|
||||
break;
|
||||
|
||||
case 'mmin':
|
||||
$value /= 25.4;
|
||||
break;
|
||||
|
||||
case 'mmcm':
|
||||
$value /= 10;
|
||||
break;
|
||||
|
||||
case 'mmpt':
|
||||
$value *= 72 / 25.4;
|
||||
break;
|
||||
|
||||
case 'ptin':
|
||||
$value /= 72;
|
||||
break;
|
||||
|
||||
case 'ptcm':
|
||||
$value *= 2.54 / 72;
|
||||
break;
|
||||
|
||||
case 'ptmm':
|
||||
$value *= 25.4 / 72;
|
||||
break;
|
||||
}
|
||||
if (!is_null($precision)) {
|
||||
$value = round($value, $precision);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue