print_pdf.pages.inc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. <?php
  2. /**
  3. * @file
  4. * Generates the PDF versions of the pages.
  5. *
  6. * This file is included by the print_pdf module and includes the
  7. * functions that interface with the PDF generation packages.
  8. *
  9. * @ingroup print
  10. */
  11. module_load_include('inc', 'print', 'print.pages');
  12. /**
  13. * Generate a PDF version of the printer-friendly page.
  14. *
  15. * @see print_controller()
  16. * @see _print_pdf_dompdf()
  17. * @see _print_pdf_tcpdf()
  18. */
  19. function print_pdf_controller() {
  20. // Disable caching for generated PDFs, as Drupal doesn't output the proper
  21. // headers from the cache.
  22. $GLOBALS['conf']['cache'] = FALSE;
  23. $args = func_get_args();
  24. $path = filter_xss(implode('/', $args));
  25. $cid = isset($_GET['comment']) ? (int) $_GET['comment'] : NULL;
  26. // Handle the query.
  27. $query = $_GET;
  28. unset($query['q']);
  29. $node = NULL;
  30. if (!empty($path)) {
  31. if ($alias = drupal_lookup_path('source', $path)) {
  32. // Alias.
  33. $path_arr = explode('/', $alias);
  34. $node = node_load($path_arr[1]);
  35. }
  36. elseif (ctype_digit($args[0])) {
  37. // Normal nid.
  38. $node = node_load($args[0]);
  39. }
  40. $pdf_filename = variable_get('print_pdf_filename', PRINT_PDF_FILENAME_DEFAULT);
  41. if (!empty($pdf_filename) && !empty($node)) {
  42. $pdf_filename = token_replace($pdf_filename, array('node' => $node), array('clear' => TRUE));
  43. }
  44. else {
  45. $pdf_filename = token_replace($pdf_filename, array('site'), array('clear' => TRUE));
  46. if (empty($pdf_filename)) {
  47. // If empty, use a fallback solution.
  48. $pdf_filename = str_replace('/', '_', $path);
  49. }
  50. }
  51. }
  52. else {
  53. $pdf_filename = 'page';
  54. }
  55. if (function_exists('transliteration_clean_filename')) {
  56. $pdf_filename = transliteration_clean_filename($pdf_filename, language_default('language'));
  57. }
  58. drupal_alter('print_pdf_filename', $pdf_filename, $path);
  59. $pdf = print_pdf_generate_path($path, $query, $cid, $pdf_filename . '.pdf');
  60. if ($pdf == NULL) {
  61. drupal_goto($path);
  62. exit;
  63. }
  64. $nodepath = (isset($node->nid)) ? 'node/' . $node->nid : drupal_get_normal_path($path);
  65. db_merge('print_pdf_page_counter')
  66. ->key(array('path' => substr($nodepath, 0, 255)))
  67. ->fields(array(
  68. 'totalcount' => 1,
  69. 'timestamp' => REQUEST_TIME,
  70. ))
  71. ->expression('totalcount', 'totalcount + 1')
  72. ->execute();
  73. drupal_exit();
  74. }
  75. /**
  76. * Gennerate a PDF for a given Drupal path.
  77. *
  78. * @param string $path
  79. * path of the page to convert to PDF.
  80. * @param array $query
  81. * (Optional) array of key/value pairs as used in the url() function for the
  82. * query.
  83. * @param int $cid
  84. * (Optional) comment ID of the comment to render.
  85. * @param string $pdf_filename
  86. * (Optional) filename of the generated PDF.
  87. * @param string $view_mode
  88. * (Optional) view mode to be used when rendering the content.
  89. *
  90. * @return string|null
  91. * generated PDF page, or NULL in case of error
  92. *
  93. * @see print_pdf_controller()
  94. */
  95. function print_pdf_generate_path($path, $query = NULL, $cid = NULL, $pdf_filename = NULL, $view_mode = PRINT_VIEW_MODE) {
  96. global $base_url;
  97. $link = print_pdf_print_link();
  98. $node = print_controller($path, $link['format'], $cid, $view_mode);
  99. if ($node) {
  100. // Call the tool's hook_pdf_tool_info(), to see if CSS must be expanded.
  101. $pdf_tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT));
  102. $cache_enabled = variable_get('print_pdf_cache_enabled', PRINT_PDF_CACHE_ENABLED_DEFAULT);
  103. $function = $pdf_tool[0] . '_pdf_tool_info';
  104. $info = function_exists($function) ? $function() : array();
  105. $expand = isset($info['expand_css']) ? $info['expand_css'] : FALSE;
  106. $html = theme('print', array(
  107. 'node' => $node,
  108. 'query' => $query,
  109. 'expand_css' => $expand,
  110. 'format' => $link['format'],
  111. ));
  112. // Img elements must be set to absolute.
  113. $pattern = '!<(img\s[^>]*?)>!is';
  114. $html = preg_replace_callback($pattern, '_print_rewrite_urls', $html);
  115. // Convert the a href elements, to make sure no relative links remain.
  116. $pattern = '!<(a\s[^>]*?)>!is';
  117. $html = preg_replace_callback($pattern, '_print_rewrite_urls', $html);
  118. // And make anchor links relative again, to permit in-PDF navigation.
  119. $html = preg_replace("!${base_url}/" . $link['path'] . '/.*?#!', '#', $html);
  120. $meta = array(
  121. 'node' => $node,
  122. 'url' => url(drupal_get_path_alias(empty($node->nid) ? $node->path : "node/$node->nid"), array('absolute' => TRUE)),
  123. );
  124. if (isset($node->name)) {
  125. $meta['name'] = $node->name;
  126. }
  127. if (isset($node->title)) {
  128. $meta['title'] = $node->title;
  129. }
  130. $paper_size = isset($node->print_pdf_size) ? $node->print_pdf_size : NULL;
  131. $page_orientation = isset($node->print_pdf_orientation) ? $node->print_pdf_orientation : NULL;
  132. $pdf = '';
  133. $cachemiss = FALSE;
  134. $cachefile = '';
  135. if ($cache_enabled && isset($node->nid)) {
  136. // See if the file exists in the cache.
  137. $cachefile = drupal_realpath(print_pdf_cache_dir()) . '/' . $node->nid . '.pdf';
  138. if (is_readable($cachefile)) {
  139. // Get the PDF content from the cached file.
  140. $pdf = file_get_contents($cachefile);
  141. if ($pdf === FALSE) {
  142. watchdog('print_pdf', 'Failed to read from cached file %file', array('%file' => $cachefile), WATCHDOG_ERROR);
  143. }
  144. }
  145. else {
  146. $cachemiss = TRUE;
  147. }
  148. }
  149. // If cache is off or file is not cached, generate one from scratch.
  150. if (empty($pdf)) {
  151. $pdf = print_pdf_generate_html($html, $meta, NULL, $paper_size, $page_orientation);
  152. }
  153. if (!empty($pdf)) {
  154. // A PDF was created, save it to cache if configured.
  155. if ($cachemiss) {
  156. if (file_unmanaged_save_data($pdf, $cachefile, FILE_EXISTS_REPLACE) == FALSE) {
  157. watchdog('print_pdf', 'Failed to write to "%f".', array('%f' => $cachefile), WATCHDOG_ERROR);
  158. }
  159. }
  160. return $pdf_filename ? print_pdf_dispose_content($pdf, $pdf_filename) : $pdf;
  161. }
  162. }
  163. return NULL;
  164. }