Создание PDF версии страницы в Drupal 7

Перед нами стояла задача создать версию страницы в PDF формате, конечно же используя как можно больше стандартных возможностей Drupal, и существующих модулей расширения с возможностью дальнейшей миграции.

Для этой задачи был взят модуль «Print» - этот модуль позволяет создавать не только стандартные «node» в виде pdf, но и версию для печати, отправку на email.

Процесс установки модуля выполняется в несколько этапов:

  • Качаем по FTP или просто копируем распакованный модуль «Print» в директорию «/sites/all/modules/»
  • Переходим в админку сайта модули и выбираем необходимые нам модули, в данном случае выбран: TCPDF library handler, Printer-friendly pages, PDF version, Printer-friendly pages UI
  • Устанавливаем выбранные модули

Установка модуля Print в Drupal 7

TCPDF library handler — этот модуль служит для связи библиотеки «tcpdf» - с возможностями самого модуля и по сути является функцией обратного вызова, мой выбор остановился именно на ней потому что она достаточно надежна и проверена временем.

Все установлено но теперь нам нужно скачать саму библиотеку «tcpdf» иначе наш модуль не будет работать, если мы перейдет по ссылки «/admin/config/user-interface/print/pdf» то увидем сообщение которое потребует от нас загрузить эту библиотеку. Качаем исходники этой библиотечки и кладем их в директорию «/sites/all/libraries/tcpdf».

Настройка pdf модуля Print Drupal7

Все отлично и у нас все установлено, но не хватает кнопок для отправки на печать, для вывода нам потребуется перейди в раздел «Структура / Блоки», выбрать блок «Printer, email and PDF versions» в нужный регион.

Кнопка печати PDF в Drupal 7

Давайте перейдем к самому главному, это темизации вывода нашей страницы версии для печати. Для этого мы можем создать отдельный вариант отображения во вкладке настройки отображения типа материала по умолчанию, выберем в «Включить настройки для следующих способов отображения» - «Печать»

Настройка отображения Drupal7 страницы версия для печати

Настроим отображение необходимых полей страницы «Node».

Настройка полей версия для печати Drupal7

Следующим шагом будет создание отдельно шаблона страницы «Node» печати, для этого скопируйте файл «print.tpl.php» который находится в директории «/sites/all/modules/print» в директорию с нашей темой «/sites/all/themes/название темы/templates»

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language; ?>" version="XHTML+RDFa 1.0"
dir="<?php print $language->dir; ?>">
<head>
<?php print $head; ?>
<base href='<?php print $url ?>'/>
<title><?php print $print_title; ?></title>
<?php print $scripts; ?>
<?php if (isset($sendtoprinter)) print $sendtoprinter; ?>
<?php print $robots_meta; ?>
<?php if (theme_get_setting('toggle_favicon')): ?>
<link rel='shortcut icon' href='<?php print theme_get_setting('favicon') ?>' type='image/x-icon'/>
<?php endif; ?>

<?php print $css; ?>
</head>
<body>
<div id="wrapper-page-print">
<?php if (!empty($message)): ?>
<div class="print-message"><?php print $message; ?></div>
<?php endif; ?>
<?php if ($print_logo): ?>
<div class="print-logo"><?php print $print_logo; ?></div>
<?php endif; ?>
<div class="print-site_name"><?php print theme('print_published'); ?></div>

<div class="print-breadcrumb"><?php print theme('print_breadcrumb', array('node' => $node)); ?></div>
<hr class="print-hr"/>
<?php if (!isset($node->type)): ?>
<h2 class="print-title"><?php print $print_title; ?></h2>
<?php endif; ?>
<div class="print-content"><?php print $content; ?></div>
<div class="print-footer"><?php print theme('print_footer'); ?></div>
<hr class="print-hr"/>
<?php if ($sourceurl_enabled): ?>
<div class="print-source_url">
<?php print theme('print_sourceurl', array('url' => $source_url, 'node' => $node, 'cid' => $cid)); ?>
</div>
<?php endif; ?>
<div class="print-links"><?php print theme('print_url_list'); ?></div>
<?php print $footer_scripts; ?>
</div>
</body>
</html>

Для переопрделения шаблона мы можем воспользоваться следующим патерном:

/**
* print[--format][--node--content-type[--nodeid]].tpl.php
*
* The following suggestions can be used:
* 1. print--format--node--content-type--nodeid.tpl.php
* 2. print--format--node--content-type.tpl.php
* 3. print--format.tpl.php
* 4. print--node--content-type--nodeid.tpl.php
* 5. print--node--content-type.tpl.php
* 6. print.tpl.php
**/

После как мы доработали нашу таблицу стилей и получили презентабельную печатную страницу, осталось доработать PDF версию страницы. Эта задача не такая простая и решить ее простой правкой HTML и CSS не получится так как PDF формат имеет свой собственный синтаксист, но в модуле «Print» заложена возможности переопределения стандартной функции форматирования - хук название темы_print_pdf_tcpdf_content(&$vars)

function theme_print_pdf_tcpdf_content($vars) {
$pdf = $vars['pdf'];
// set content font
$pdf->setFont($vars['font'][0], $vars['font'][1], $vars['font'][2]);

// Remove the logo, published, breadcrumb and footer from the main content
preg_match('!<body.*?>(.*)</body>!sim', $vars['html'], $matches);
$pattern = '!(?:<div class="print-(?:logo|site_name|breadcrumb|footer)">.*?</div>|<hr class="print-hr" />)!si';
$matches[1] = preg_replace($pattern, '', $matches[1]);

// Make CCK fields look better
$matches[1] = preg_replace('!(<div class="field.*?>)\s*!sm', '$1', $matches[1]);
$matches[1] = preg_replace('!(<div class="field.*?>.*?</div>)\s*!sm', '$1', $matches[1]);
$matches[1] = preg_replace('!<div( class="field-label.*?>.*?)</div>!sm', '<strong$1</strong>', $matches[1]);

// Since TCPDF's writeHTML is so bad with <p>, do everything possible to make it look nice
$matches[1] = preg_replace('!<(?:p(|\s+.*?)/?|/p)>!i', '<br$1 />', $matches[1]);
$matches[1] = str_replace(array('<div', 'div>'), array('<span', 'span><br />'), $matches[1]);
do {
$prev = $matches[1];
$matches[1] = preg_replace('!(</span>)<br />(\s*?</span><br />)!s', '$1$2', $matches[1]);
} while ($prev != $matches[1]);

@$pdf->writeHTML($matches[1]);

return $pdf;
}

Переведенный листинг выше нам не подходит и использует общее применение, так как выравнивание картинок и стилизация полей не устраивает по внешнему виду. Для решения этой задачи нужно распарсить html содержимое страницы печати и использовать API библиотеки tcpdf. В качестве парсера будем использовать билетику «PHP Simple HTML DOM Parser» его методы по своему синтаксису напоминают «jQuery» что значительно облегчает работу с библиотекой.

function sms_print_pdf_tcpdf_content(&$vars)
{

$pdf = $vars['pdf'];

$node = node_load(arg(1));

if ($node->type == 'equipment') {
$pdf->setFont($vars['font'][0], $vars['font'][1], $vars['font'][2]);
$html = str_get_html($vars['html']);

$images = $html->find('.item-img .img-responsive');


$x = 15;
$y = 20;
$w = 55;
$h = 40;
foreach ($images as $img) {

$pdf->Image($img->src, $x, $y, $w, $h, '', '', 'M', false, 300, '', false, false, 1, false, false, false);
$x = $x + $w + 2;


if ($x >= 160) {
$y = $y + $h + 2;
$x = 15;
}
}

$des = $html->find('.field-name-body .field-item', 0);

$pdf->writeHTMLCell(null, null, 15, $y + $h + 10, $des->innertext, 0, 1);

$table = $html->find('.field-name-field-specifications', 0);

$table->find('table', 0)->setAttribute('style', 'border-collapse: separate; border-spacing: 4px; width: 100%; margin-left: -4px; margin-right: -4px;');
$table->find('table thead tr', 0)->setAttribute('style', 'background-color: #144074; color: #fff;');

foreach ($table->find('table td, table th') as $td) {
$td->setAttribute('style', 'padding: 20px;');
}
foreach ($table->find('tbody tr') as $k => $tr) {
if ($k > 0) {
$tr->setAttribute('style', ' background-color: #f2f2f2; color: #3d3d3d;');
}

}

$pdf->writeHTML('<br><div><strong>' . $table->find('.field-label', 0)->innertext . '</strong>' . $table->find('.field-items', 0)->innertext . '</div>', true);


$price = $html->find('.box-price', 0);

$priceHtml = "<strong>" . $price->find('.field-name-field-price .field-label', 0)->innertext . "</strong>";
$priceHtml .= $price->find('.field-name-field-price .field-item', 0)->innertext;
$priceHtml .= $price->find('.field-name-field-currency .field-item', 0)->innertext;

$pdf->writeHTML($priceHtml, true);


$contact = $html->find('.wrapp-contact', 0);

$contactHtml = "<br/><br/><strong>" . $contact->find('.label-contact', 0)->innertext . "</strong><br/>";

foreach ($contact->find('.field') as $f) {
$contactHtml .= '<br/><span><strong>' . $f->find('.field-label', 0)->innertext . '</strong>' . $f->find('.field-item', 0)->innertext . '</span>';
}

$pdf->writeHTML($contactHtml, true);

}


return $pdf;
}

В итоге мы получили внешне PDF документ который удовлетворяет требованиям заказчика и минимальными затратами по времени.

Результат страницы темизации печати Drupal7


Close