Issue #1188232: remove deprecated call to AliasNbPages() in TCPDF.
[project/print.git] / print_pdf / print_pdf.pages.inc
index be44839..29443e3 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-// $Id$
 
 /**
  * @file
@@ -11,7 +10,7 @@
  * @ingroup print
  */
 
-require_once(DRUPAL_ROOT . '/' . drupal_get_path('module', 'print') . '/print.pages.inc');
+module_load_include('inc', 'print', 'print.pages');
 
 /**
  * Generate a PDF version of the printer-friendly page
@@ -21,7 +20,7 @@ require_once(DRUPAL_ROOT . '/' . drupal_get_path('module', 'print') . '/print.pa
  * @see _print_pdf_tcpdf()
  */
 function print_pdf_controller() {
-  global $base_url, $language;
+  global $base_url;
 
   // Disable caching for generated PDFs, as Drupal doesn't ouput the proper headers from the cache
   $GLOBALS['conf']['cache'] = FALSE;
@@ -30,8 +29,35 @@ function print_pdf_controller() {
   $path = implode('/', $args);
   $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;
 
-  $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
+  $pdf_filename = variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT);
+  if (!empty($pdf_filename)) {
+    $pdf_filename = token_replace($pdf_filename, array('node' => $node)) . '.pdf';
+  }
+  else {
+    $pdf_filename = str_replace('/', '_', $path) . '.pdf';
+  }
+  if (function_exists('transliteration_clean_filename')) {
+    $pdf_filename = transliteration_clean_filename($pdf_filename, language_default('language'));
+  }
+
+  $pdf = print_pdf_generate_path($path, $cid, $pdf_filename);
+  if ($pdf == NULL) {
+    drupal_goto($print['url']);
+    exit;
+  }
 
+  $nodepath = (isset($node->path)) ? drupal_get_normal_path($node->path) : 'node/' . $path;
+  db_merge('print_pdf_page_counter')
+    ->key(array('path' => $nodepath))
+    ->fields(array(
+        'totalcount' => 1,
+        'timestamp' => REQUEST_TIME,
+    ))
+    ->expression('totalcount', 'totalcount + :inc', array(':inc' => 1))
+    ->execute();
+}
+
+function print_pdf_generate_path($path, $cid = NULL, $pdf_filename = NULL) {
   $print = print_controller($path, $cid, PRINT_PDF_FORMAT);
   if ($print === FALSE) {
     return;
@@ -42,33 +68,12 @@ function print_pdf_controller() {
   $print['content'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['content']);
   $print['logo'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['logo']);
   $print['footer_message'] = preg_replace_callback($pattern, '_print_rewrite_urls', $print['footer_message']);
-  // And converted from private to public paths
-  switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
-    case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
-    case LANGUAGE_NEGOTIATION_PATH:
-      $lang = $language->language;
-      break;
-    default:
-      $lang = '';
-      break;
-  }
-  $file_downloads = variable_get('file_default_scheme', 'public');
-  if ($file_downloads == 'private') {
-    $pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?system/files/([^>]*?>)!is";
-    $replacement = '$1file://' . realpath(file_directory_path()) . '/$2';
-  }
-  else {
-    $pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?([^>]*?>)!is";
-    $replacement = '$1file://'. realpath($_SERVER["DOCUMENT_ROOT"].base_path()) .'/$2';
-  }
-  $print['content'] = preg_replace($pattern, $replacement, $print['content']);
-  $print['logo'] = preg_replace($pattern, $replacement, $print['logo']);
-  $print['footer_message'] = preg_replace($pattern, $replacement, $print['footer_message']);
+
   // Send to printer option causes problems with PDF
   $print['sendtoprinter'] = '';
 
   $node = $print['node'];
-  $html = theme('print_page', array('print' => $print, 'type' => PRINT_PDF_FORMAT, 'node' => $node));
+  $html = theme('print', array('print' => $print, 'type' => PRINT_PDF_FORMAT, 'node' => $node));
 
   // Convert the a href elements, to make sure no relative links remain
   $pattern = '!<(a\s[^>]*?)>!is';
@@ -76,39 +81,65 @@ function print_pdf_controller() {
   // And make anchor links relative again, to permit in-PDF navigation
   $html = preg_replace("!${base_url}/" . PRINTPDF_PATH . "/.*?%2523!", '#', $html);
 
-  $pdf_filename = variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT);
-  if (!empty($pdf_filename)) {
-    $pdf_filename = token_replace($pdf_filename, array('node' => $node)) . '.pdf';
-  }
-  else {
-    $pdf_filename = str_replace('/', '_', $path) . '.pdf';
-  }
-  if (function_exists('transliteration_clean_filename')) {
-    $pdf_filename = transliteration_clean_filename($pdf_filename, language_default('language'));
-  }
+  return print_pdf_generate_html($print, $html, $pdf_filename);
+}
+
+function print_pdf_generate_html($print, $html, $filename = NULL) {
+  $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
 
   if (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
-    _print_pdf_dompdf($print, $html, $pdf_filename);
+    return _print_pdf_dompdf($print, $html, $filename);
   }
   elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
-    _print_pdf_tcpdf($print, $html, $pdf_filename);
+    return _print_pdf_tcpdf($print, $html, $filename);
   }
   elseif (substr(basename($print_pdf_pdf_tool, '.exe'), 0, 11) == 'wkhtmltopdf') {
-    _print_pdf_wkhtmltopdf($print, $html, $pdf_filename);
+    return _print_pdf_wkhtmltopdf($print, $html, $filename);
   }
-  else {
+  elseif ($filename) {
     return drupal_not_found();
   }
+  return NULL;
+}
 
-  $nodepath = (isset($node->path)) ? drupal_get_normal_path($node->path) : 'node/' . $path;
-  db_merge('print_pdf_page_counter')
-    ->key(array('path' => $nodepath))
-    ->fields(array(
-        'totalcount' => 1,
-        'timestamp' => REQUEST_TIME,
-    ))
-    ->expression('totalcount', 'totalcount + :inc', array(':inc' => 1))
-    ->execute();
+/**
+ * Convert image paths to the file:// protocol
+ *
+ * In some Drupal setups, the use of the 'private' filesystem or Apache's
+ * configuration prevent access to the images of the page. This function
+ * tries to circumnvent those problems by accessing files in the local
+ * filesystem.
+ *
+ * @param $html
+ *   contents of the post-processed template already with the node data
+ * @see print_pdf_controller()
+ */
+function _print_pdf_file_access_images($html) {
+  global $base_url, $language;
+
+  // TODO: This needs to be rewritten from scratch for Drupal 7
+/*
+  // And converted from private to public paths
+  switch (variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE)) {
+    case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
+    case LANGUAGE_NEGOTIATION_PATH:
+      $lang = $language->language;
+      break;
+    default:
+      $lang = '';
+      break;
+  }
+  $file_downloads = variable_get('file_default_scheme', 'public');
+  if ($file_downloads == 'private') {
+    $pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?system/files/([^>]*?>)!is";
+    $replacement = '$1file://' . realpath(file_directory_path()) . '/$2';
+    $html = preg_replace($pattern, $replacement, $html);
+  }
+  $pattern = "!(<img\s[^>]*?src\s*?=\s*?['\"]?)${base_url}/(?:(?:index.php)?\?q=)?(?:${lang}/)?([^>]*?>)!is";
+  $replacement = '$1file://' . dirname($_SERVER['SCRIPT_FILENAME']) . '/$2';
+  $html = preg_replace($pattern, $replacement, $html);
+*/
+  return $html;
 }
 
 /**
@@ -122,7 +153,7 @@ function print_pdf_controller() {
  *   name of the PDF file to be generated
  * @see print_pdf_controller()
  */
-function _print_pdf_dompdf($print, $html, $filename) {
+function _print_pdf_dompdf($print, $html, $filename = NULL) {
   $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
   $print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
   $print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
@@ -138,6 +169,9 @@ function _print_pdf_dompdf($print, $html, $filename) {
   require_once(DRUPAL_ROOT . '/' . $print_pdf_pdf_tool);
   spl_autoload_register('DOMPDF_autoload');
 
+  // Try to use local file access for image files
+  $html = _print_pdf_file_access_images($html);
+
   // dompdf seems to have problems with something in system.css so let's not use it
   $html = preg_replace('!<link.*?modules/system/system.css.*?/>!', '', $html);
 
@@ -184,7 +218,13 @@ function _print_pdf_dompdf($print, $html, $filename) {
   $dompdf->load_html($html);
 
   $dompdf->render();
-  $dompdf->stream($filename, array('Attachment' => ($print_pdf_content_disposition == 2)));
+  if ($filename) {
+    $dompdf->stream($filename, array('Attachment' => ($print_pdf_content_disposition == 2)));
+    return TRUE;
+  }
+  else {
+    return $dompdf->output();
+  }
 }
 
 /**
@@ -198,7 +238,7 @@ function _print_pdf_dompdf($print, $html, $filename) {
  *   name of the PDF file to be generated
  * @see print_pdf_controller()
  */
-function _print_pdf_tcpdf($print, $html, $filename) {
+function _print_pdf_tcpdf($print, $html, $filename = NULL) {
   global $base_url, $language;
 
   $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
@@ -220,6 +260,9 @@ function _print_pdf_tcpdf($print, $html, $filename) {
     define('K_SMALL_RATIO', 2/3);
   }
 
+  // Try to use local file access for image files
+  $html = _print_pdf_file_access_images($html);
+
   // Decode HTML entities in image filenames
   $pattern = "!<img\s[^>]*?src\s*?=\s*?['\"]?{$base_url}[^>]*?>!is";
   $html = preg_replace_callback($pattern, create_function('$matches', 'return html_entity_decode($matches[0], ENT_QUOTES);'), $html);
@@ -228,13 +271,7 @@ function _print_pdf_tcpdf($print, $html, $filename) {
   $html = preg_replace($pattern, '$1$2', $html);
 
   require_once(DRUPAL_ROOT . '/' . $print_pdf_pdf_tool);
-  if (strpos(PDF_PRODUCER, 'PHP4') === FALSE) {
-    require_once(DRUPAL_ROOT . '/' . drupal_get_path('module', 'print_pdf') . '/print_pdf.class.inc');
-  }
-  else {
-    drupal_set_message(t("The PHP4 version of TCPDF is not supported. Please upgrade it."), 'error', FALSE);
-    drupal_goto($_GET['q']);
-  }
+  module_load_include('inc', 'print_pdf', 'print_pdf.class');
 
   $font = Array(
     check_plain(variable_get('print_pdf_font_family', PRINT_PDF_FONT_FAMILY_DEFAULT)),
@@ -253,6 +290,7 @@ function _print_pdf_tcpdf($print, $html, $filename) {
   $keys = implode(' ', explode("\n", trim(strip_tags($print['taxonomy']))));
   $pdf->SetKeywords($keys);
   $pdf->setPDFVersion('1.6');
+  $pdf->setFontSubsetting(variable_get('print_pdf_font_subsetting',FALSE));
 
   if ($language->direction == LANGUAGE_RTL) {
     $pdf->setRTL(TRUE);
@@ -262,9 +300,6 @@ function _print_pdf_tcpdf($print, $html, $filename) {
   $pdf = theme('print_pdf_tcpdf_footer', array('pdf' => $pdf, 'html' => $html, 'font' => $font));
   $pdf = theme('print_pdf_tcpdf_page', array('pdf' => $pdf));
 
-  //initialize document
-  $pdf->AliasNbPages();
-
   // add a page
   $pdf->AddPage();
 
@@ -276,9 +311,15 @@ function _print_pdf_tcpdf($print, $html, $filename) {
   // try to recover from any warning/error
   ob_clean();
 
-  //Close and output PDF document
-  $output_dest = ($print_pdf_content_disposition == 2) ? 'D' : 'I';
-  $pdf->Output($filename, $output_dest);
+  if ($filename) {
+    //Close and output PDF document
+    $output_dest = ($print_pdf_content_disposition == 2) ? 'D' : 'I';
+    $pdf->Output($filename, $output_dest);
+    return TRUE;
+  }
+  else {
+    return $pdf = $pdf->Output('', 'S');
+  }
 }
 
 /**
@@ -292,7 +333,7 @@ function _print_pdf_tcpdf($print, $html, $filename) {
  *   name of the PDF file to be generated
  * @see print_pdf_controller()
  */
-function _print_pdf_wkhtmltopdf($print, $html, $filename) {
+function _print_pdf_wkhtmltopdf($print, $html, $filename = NULL) {
   $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
   $print_pdf_paper_size = variable_get('print_pdf_paper_size', PRINT_PDF_PAPER_SIZE_DEFAULT);
   $print_pdf_page_orientation = variable_get('print_pdf_page_orientation', PRINT_PDF_PAGE_ORIENTATION_DEFAULT);
@@ -305,6 +346,20 @@ function _print_pdf_wkhtmltopdf($print, $html, $filename) {
     $print_pdf_wkhtmltopdf_options = token_replace($print_pdf_wkhtmltopdf_options, array('node' => $print['node']));
   }
 
+  $version = _print_pdf_wkhtmltopdf_version();
+
+  // 0.10.0 beta2 identifies itself as 0.9.9
+  if (version_compare($version, '0.9.9', '>=')) {
+    $print_pdf_wkhtmltopdf_options = '--disable-local-file-access ' . $print_pdf_wkhtmltopdf_options;
+  }
+  elseif (version_compare($version, '0.9.6', '>=')) {
+    $print_pdf_wkhtmltopdf_options = '--disallow-local-file-access ' . $print_pdf_wkhtmltopdf_options;
+  }
+  else {
+    drupal_goto($print['url']);
+    exit;
+  }
+
   $descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
   $cmd = realpath($print_pdf_pdf_tool) . " --page-size $print_pdf_paper_size --orientation $print_pdf_page_orientation --dpi $dpi $print_pdf_wkhtmltopdf_options - -";
 
@@ -328,22 +383,27 @@ function _print_pdf_wkhtmltopdf($print, $html, $filename) {
   }
 
   if (!empty($pdf)) {
-    if (headers_sent()) {
-      die("Unable to stream pdf: headers already sent");
-    }
-    header("Cache-Control: private");
-    header("Content-Type: application/pdf");
+    if ($filename) {
+      if (headers_sent()) {
+        die("Unable to stream pdf: headers already sent");
+      }
+      header("Cache-Control: private");
+      header("Content-Type: application/pdf");
 
-    $attachment =  ($print_pdf_content_disposition == 2) ?  "attachment" :  "inline";
+      $attachment =  ($print_pdf_content_disposition == 2) ?  "attachment" :  "inline";
 
-    header("Content-Disposition: $attachment; filename=\"$filename\"");
+      header("Content-Disposition: $attachment; filename=\"$filename\"");
 
-    echo $pdf;
-    flush();
+      echo $pdf;
+      flush();
+      return TRUE;
+    }
+    else {
+      return $pdf;
+    }
   }
   else {
-    drupal_goto($print['url']);
-    exit;
+    return NULL;
   }
 }
 
@@ -421,7 +481,7 @@ function theme_print_pdf_tcpdf_header($vars) {
   // set header margin
   $pdf->SetHeaderMargin(5);
   // set header data
-  $pdf->SetHeaderData($logo, 10 * $ratio, html_entity_decode($tpl_title[1], ENT_QUOTES, 'UTF-8'), strip_tags($tpl_site_name[1]));
+  $pdf->SetHeaderData($logo, 10 * $ratio, html_entity_decode($tpl_title[1], ENT_QUOTES, 'UTF-8'), html_entity_decode(strip_tags($tpl_site_name[1]), ENT_QUOTES, 'UTF-8'));
 
   return $pdf;
 }
@@ -440,9 +500,7 @@ function theme_print_pdf_tcpdf_page($vars) {
   // set auto page breaks
   $pdf->SetAutoPageBreak(TRUE, 15);
   // set image scale factor
-  sscanf(PDF_PRODUCER, "TCPDF %d.%d.%d", $major, $minor, $build);
-  $imagescale = (($major >= 4) && ($minor >= 6) && ($build >= 2)) ? 1 : 4;
-  $pdf->setImageScale($imagescale);
+  $pdf->setImageScale(1);
   // set image compression quality
   $pdf->setJPEGQuality(100);
 
@@ -524,7 +582,7 @@ function theme_print_pdf_tcpdf_footer($vars) {
 function theme_print_pdf_tcpdf_footer2($vars) {
   $pdf = $vars['pdf'];
   //Position at 1.5 cm from bottom
-  $pdf->writeHTMLCell(0, 15, 15, -10, $pdf->footer, 0, 0, 0, TRUE, '');
+  $pdf->writeHTMLCell(0, 15, 15, $pdf->getPageHeight()-15, $pdf->footer);
 
   $ormargins = $pdf->getOriginalMargins();
   $pagenumtxt = t('Page !n of !total', array('!n' => $pdf->PageNo(), '!total' => $pdf->getAliasNbPages()));