Issue #1251222: remove fatal error when checking TCPDF version having an older versio...
[project/print.git] / print_pdf / print_pdf.module
index 79ed6a7..f5e00fb 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-// $Id$
 
 /**
  * @file
@@ -12,7 +11,10 @@ define('PRINTPDF_PATH', 'printpdf');
 
 define('PRINT_PDF_FORMAT', 'pdf');
 
+define('PRINT_PDF_LIB_PATH', 'sites/all/libraries');
+
 define('PRINT_PDF_LINK_POS_DEFAULT', 'link');
+define('PRINT_PDF_LINK_TEASER_DEFAULT', 0);
 define('PRINT_PDF_SHOW_LINK_DEFAULT', 1);
 define('PRINT_PDF_NODE_LINK_VISIBILITY_DEFAULT', 0);
 define('PRINT_PDF_NODE_LINK_PAGES_DEFAULT', '');
@@ -25,13 +27,14 @@ define('PRINT_PDF_PDF_TOOL_DEFAULT', 0);
 define('PRINT_PDF_CONTENT_DISPOSITION_DEFAULT', 2);
 define('PRINT_PDF_PAPER_SIZE_DEFAULT', 'A4');
 define('PRINT_PDF_PAGE_ORIENTATION_DEFAULT', 'portrait');
+define('PRINT_PDF_IMAGES_VIA_FILE_DEFAULT', 0);
 define('PRINT_PDF_AUTOCONFIG_DEFAULT', 1);
 define('PRINT_PDF_FONT_FAMILY_DEFAULT', 'dejavusans');
 define('PRINT_PDF_FONT_SIZE_DEFAULT', 10);
+define('PRINT_PDF_FONT_SUBSETTING_DEFAULT', 0);
 define('PRINT_PDF_FILENAME_DEFAULT', '[site-name] - [title] - [mod-yyyy]-[mod-mm]-[mod-dd]');
+define('PRINT_PDF_DOMPDF_UNICODE_DEFAULT', 0);
 define('PRINT_PDF_WKHTMLTOPDF_OPTIONS', "--footer-font-size 7 --footer-right '[page]'");
-define('PRINT_PDF_XVFB_OPTIONS', '');
-//  define('PRINT_PDF_XVFB_OPTIONS', ' -fp /usr/share/fonts/X11/misc/,/usr/share/fonts/X11/Type1/,/usr/share/fonts/X11/75dpi/,/usr/share/fonts/X11/100dpi/');
 
 /**
  * Implementation of hook_perm().
@@ -49,27 +52,27 @@ function print_pdf_theme() {
       'arguments' => array(),
     ),
     'print_pdf_dompdf_footer' => array(
-      'arguments' => array(),
+      'arguments' => array('html' => ''),
       'file' => 'print_pdf.pages.inc',
     ),
     'print_pdf_tcpdf_header' => array(
-      'arguments' => array(),
+      'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
       'file' => 'print_pdf.pages.inc',
     ),
     'print_pdf_tcpdf_page' => array(
-      'arguments' => array(),
+      'arguments' => array('pdf' => NULL),
       'file' => 'print_pdf.pages.inc',
     ),
     'print_pdf_tcpdf_content' => array(
-      'arguments' => array(),
+      'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
       'file' => 'print_pdf.pages.inc',
     ),
     'print_pdf_tcpdf_footer' => array(
-      'arguments' => array(),
+      'arguments' => array('pdf' => NULL, 'html' => '', 'font' => array()),
       'file' => 'print_pdf.pages.inc',
     ),
     'print_pdf_tcpdf_footer2' => array(
-      'arguments' => array(),
+      'arguments' => array('pdf' => NULL),
       'file' => 'print_pdf.pages.inc',
     ),
   );
@@ -89,7 +92,7 @@ function print_pdf_menu() {
     'file' => 'print_pdf.pages.inc',
   );
   $items[PRINTPDF_PATH .'/'. PRINTPDF_PATH] = array(
-    'page callback' => 'drupal_access_denied',
+    'access callback' => FALSE,
   );
   $items['admin/settings/print/pdf'] = array(
     'title' => 'PDF',
@@ -125,6 +128,7 @@ function print_pdf_block($op = 'list', $delta = 0, $edit = array()) {
   switch ($op) {
     case 'list':
       $block[0]['info'] = t('Most PDFd');
+      $block[0]['cache'] = BLOCK_CACHE_GLOBAL;
       return $block;
       break;
     case 'configure':
@@ -162,12 +166,78 @@ function print_pdf_requirements($phase) {
       $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
       if (empty($print_pdf_pdf_tool)) {
         $requirements['print_pdf_tool'] = array(
-          'title' => $t('PDF version'),
+          'title' => $t('PDF generation library'),
           'value' => $t('No PDF tool selected'),
           'description' => $t('Please configure it in the <a href="@url">PDF settings page</a>.', array('@url' => url('admin/settings/print/pdf'))),
           'severity' => REQUIREMENT_ERROR,
         );
       }
+      else {
+        if (!is_file($print_pdf_pdf_tool) || !is_readable($print_pdf_pdf_tool)) {
+          $requirements['print_pdf_tool'] = array(
+            'title' => $t('PDF generation tool'),
+            'value' => $t('File not found'),
+            'description' => $t('The currently selected PDF generation library (%file) is no longer accessible.', array('%file' => $print_pdf_pdf_tool)),
+            'severity' => REQUIREMENT_ERROR,
+          );
+        }
+        elseif (basename($print_pdf_pdf_tool) == 'dompdf_config.inc.php') {
+          $directory = dirname($print_pdf_pdf_tool) .'/lib/fonts';
+          if (!is_dir($directory) || !is_writable($directory)) {
+            $requirements['print_pdf_tool'] = array(
+              'title' => $t('DOMPDF font cache directory'),
+              'value' => $t('Non-writable permissions'),
+              'description' => $t('You must change the %fontdir permissions to be writable, as dompdf requires write-access to that directory.', array('%fontdir' => $directory)),
+              'severity' => REQUIREMENT_ERROR,
+            );
+          }
+        }
+        elseif (basename($print_pdf_pdf_tool) == 'tcpdf.php') {
+          $version = _print_pdf_tcpdf_version();
+
+          if (version_compare($version, '5.9.012', '<')) {
+            $requirements['print_pdf_tool'] = array(
+              'title' => $t('TCPDF library'),
+              'value' => $t('Unsupported version'),
+              'description' => $t('The currently selected version of TCPDF (@version) is not supported. Please update to a <a href="@url">newer version</a>.', array('@version' => $version, '@url' => url('http://www.tcpdf.org'))),
+              'severity' => REQUIREMENT_ERROR,
+            );
+          }
+
+          foreach (array('cache', 'images') as $dir) {
+            $directory = dirname($print_pdf_pdf_tool) .'/'. $dir;
+            if (!is_dir($directory) || !is_writable($directory)) {
+              $requirements['print_pdf_tool_'. $dir] = array(
+                'title' => $t('TCPDF directory'),
+                'value' => $t('Non-writable permissions'),
+                'description' => $t('You must change the %fontdir permissions to be writable, as dompdf requires write-access to that directory.', array('%fontdir' => $directory)),
+                'severity' => REQUIREMENT_ERROR,
+              );
+            }
+          }
+        }
+        elseif (substr(basename($print_pdf_pdf_tool, '.exe'), 0, 11) == 'wkhtmltopdf') {
+          if (function_exists('is_executable') && !is_executable($print_pdf_pdf_tool)) {
+            $requirements['print_pdf_tool'] = array(
+              'title' => $t('wkhtmltopdf library'),
+              'value' => $t('Non-executable permissions'),
+              'description' => $t('You must modify the permissions of the wkhtmltopdf file (%file) to make it executable.', array('%file' => $print_pdf_pdf_tool)),
+              'severity' => REQUIREMENT_ERROR,
+            );
+          }
+          else {
+            $version = _print_pdf_wkhtmltopdf_version();
+            if (version_compare($version, '0.9.6', '<')) {
+              $requirements['print_pdf_tool'] = array(
+                'title' => $t('wkhtmltopdf library'),
+                'value' => $t('Unsupported version'),
+                'description' => $t('The currently selected version of wkhtmltopdf (@version) is not supported. Please update to a <a href="@url">newer version</a>.', array('@version' => $version, '@url' => url('http://code.google.com/p/wkhtmltopdf/'))),
+                'severity' => REQUIREMENT_ERROR,
+              );
+            }
+          }
+        }
+      }
       break;
   }
   return $requirements;
@@ -253,19 +323,21 @@ function print_pdf_nodeapi(&$node, $op = 'view', $teaser, $page) {
       // Insert content corner links
       $print_pdf_link_pos = variable_get('print_pdf_link_pos', array(PRINT_PDF_LINK_POS_DEFAULT => PRINT_PDF_LINK_POS_DEFAULT));
       if (($teaser === FALSE) && !empty($print_pdf_link_pos['corner']) &&
-          isset($node->build_mode) && ($node->build_mode == NODE_BUILD_NORMAL)) {
-        $link = print_pdf_insert_link(NULL, $node);
-        if ($link) {
-          $node->content['print_links']['#value'] = preg_replace('!</span>$!', $link .'</span>', $node->content['print_links']['#value']);
-        }
+          isset($node->build_mode) && ($node->build_mode === NODE_BUILD_NORMAL)) {
+        $node->content['print_links']['#value'] .= print_pdf_insert_link(NULL, $node);
       }
       break;
     case 'load':
       _print_pdf_set_node_fields($node);
       break;
+    case 'insert':
     case 'update':
       if (user_access('administer print') || user_access('node-specific print configuration')) {
-      _print_pdf_node_conf_modify($node->nid, $node->print_pdf_display, $node->print_pdf_display_comment, $node->print_pdf_display_urllist);
+        if ($node->print_pdf_display === NULL) $node->print_pdf_display = variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
+        if ($node->print_pdf_display_comment === NULL) $node->print_pdf_display_comment = variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
+        if ($node->print_pdf_display_urllist === NULL) $node->print_pdf_display_urllist = variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
+
+        _print_pdf_node_conf_modify($node->nid, $node->print_pdf_display, $node->print_pdf_display_comment, $node->print_pdf_display_urllist);
       }
       break;
     case 'delete':
@@ -307,9 +379,9 @@ function print_pdf_form_alter(&$form, $form_state, $form_id) {
     }
     else {
       $node = $form['#node'];
-      $form['print']['print_pdf_display']['#default_value'] = isset($node->print_pdf_display) ? $node->print_pdf_display : PRINT_TYPE_SHOW_LINK_DEFAULT;
-      $form['print']['print_pdf_display_comment']['#default_value'] = isset($node->print_pdf_display_comment) ? $node->print_pdf_display_comment : PRINT_TYPE_COMMENT_LINK_DEFAULT;
-      $form['print']['print_pdf_display_urllist']['#default_value'] = isset($node->print_pdf_display_urllist) ? $node->print_pdf_display_urllist : PRINT_TYPE_URLLIST_DEFAULT;
+      $form['print']['print_pdf_display']['#default_value'] = isset($node->print_pdf_display) ? $node->print_pdf_display : variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
+      $form['print']['print_pdf_display_comment']['#default_value'] = isset($node->print_pdf_display_comment) ? $node->print_pdf_display_comment : variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
+      $form['print']['print_pdf_display_urllist']['#default_value'] = isset($node->print_pdf_display_urllist) ? $node->print_pdf_display_urllist : variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
     }
   }
 }
@@ -327,9 +399,9 @@ function _print_pdf_set_node_fields(&$node) {
   else {
     $res = FALSE;
   }
-  $node->print_pdf_display = $res ? intval($res->link) : PRINT_TYPE_SHOW_LINK_DEFAULT;
-  $node->print_pdf_display_comment = $res ? intval($res->comments) : PRINT_TYPE_COMMENT_LINK_DEFAULT;
-  $node->print_pdf_display_urllist = $res ? intval($res->url_list) : PRINT_TYPE_URLLIST_DEFAULT;
+  $node->print_pdf_display = $res ? intval($res->link) : variable_get('print_pdf_display_'. $node->type, PRINT_TYPE_SHOW_LINK_DEFAULT);
+  $node->print_pdf_display_comment = $res ? intval($res->comments) : variable_get('print_pdf_display_comment_'. $node->type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
+  $node->print_pdf_display_urllist = $res ? intval($res->url_list) : variable_get('print_pdf_display_urllist_'. $node->type, PRINT_TYPE_URLLIST_DEFAULT);
 }
 
 /**
@@ -346,16 +418,10 @@ function _print_pdf_set_node_fields(&$node) {
  *   value of the url_list field (0 or 1)
  */
 function _print_pdf_node_conf_modify($nid, $link, $comments, $url_list) {
-  if (($link == PRINT_TYPE_SHOW_LINK_DEFAULT) && ($comments == PRINT_TYPE_COMMENT_LINK_DEFAULT) &&
-      ($url_list == PRINT_TYPE_URLLIST_DEFAULT)) {
-    db_query("DELETE FROM {print_pdf_node_conf} WHERE nid = %d", $nid);
-  }
-  else {
     db_query("UPDATE {print_pdf_node_conf} SET link = %d, comments = %d, url_list = %d WHERE nid = %d", $link, $comments, $url_list, $nid);
     if (!db_affected_rows()) {
-      db_query("INSERT INTO {print_pdf_node_conf} (nid, link, comments, url_list) VALUES (%d, %d, %d, %d)", $nid, $link, $comments, $url_list);
+      @db_query("INSERT INTO {print_pdf_node_conf} (nid, link, comments, url_list) VALUES (%d, %d, %d, %d)", $nid, $link, $comments, $url_list);
     }
-  }
 }
 
 /**
@@ -459,13 +525,14 @@ function print_pdf_insert_link($path = NULL, $node = NULL) {
  */
 function print_pdf_link_allowed($args) {
   $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
-  if (!empty($args['teaser']) || !user_access('access PDF version') || (empty($print_pdf_pdf_tool))) {
-    // If showing only the teaser or the user is not allowed or link is disabled
+  if ((!empty($args['teaser']) && !variable_get('print_pdf_link_teaser', PRINT_PDF_LINK_TEASER_DEFAULT))
+      || !user_access('access PDF version') || (empty($print_pdf_pdf_tool))) {
+    // If the teaser link is disabled or the user is not allowed
     return FALSE;
   }
   if (!empty($args['path'])) {
     $nid = preg_replace('!^node/!', '', drupal_get_normal_path($args['path']));
-    if (is_numeric($nid)) {
+    if (ctype_digit($nid)) {
       $args['node'] = node_load($nid);
     }
   }
@@ -473,36 +540,33 @@ function print_pdf_link_allowed($args) {
     static $node_type = FALSE;
 
     $node = $args['node'];
-    if ($node_type === FALSE) {
-      if (isset($node->type)) {
-        $node_type = $node->type;
-      }
-      else {
-        $node_type = '';
-      }
+    if (isset($node->type)) {
+      $node_type = $node->type;
     }
     // Node
     $print_pdf_node_link_visibility = variable_get('print_pdf_node_link_visibility', PRINT_PDF_NODE_LINK_VISIBILITY_DEFAULT);
     $print_pdf_node_link_pages = variable_get('print_pdf_node_link_pages', PRINT_PDF_NODE_LINK_PAGES_DEFAULT);
 
-    if (!_print_page_match($print_pdf_node_link_visibility, $print_pdf_node_link_pages)) {
+    if (!_print_page_match($print_pdf_node_link_visibility, "node/". $node->nid, $print_pdf_node_link_pages)) {
       // Page not in visibility list
       return FALSE;
     }
     elseif (isset($args['type']) && ($args['type'] == 'comment') && isset($node_type)) {
       // Link is for a comment, return the configured setting
-      $res = db_fetch_object(db_query("SELECT comments FROM {print_pdf_node_conf} WHERE nid = %d", $node->nid));
-      $print_display_comment = $res ? intval($res->comments) : PRINT_TYPE_COMMENT_LINK_DEFAULT;
-      if (($print_display_comment) ||
-          variable_get('print_pdf_display_comment_'. $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT)) {
+      // Cache this statically to avoid duplicate queries for every comment.
+      static $res = array();
+      if (!isset($res[$node->nid])) {
+        $res[$node->nid] = db_fetch_object(db_query("SELECT comments FROM {print_pdf_node_conf} WHERE nid = %d", $node->nid));
+      }
+      $print_display_comment = $res ? intval($res[$node->nid]->comments) : variable_get('print_pdf_display_comment_'. $node_type, PRINT_TYPE_COMMENT_LINK_DEFAULT);
+      if ($print_display_comment) {
         return PRINT_ALLOW_NORMAL_LINK;
       }
     }
     else {
       // Node link
-      if ((!$node->print_pdf_display) || (isset($node_type) &&
-          !variable_get('print_pdf_display_'. $node_type, PRINT_TYPE_SHOW_LINK_DEFAULT))) {
-        // Link for this node type is disabled
+      if (!$node->print_pdf_display) {
+        // Link for this node is disabled
         return FALSE;
       }
       elseif (isset($node->book)) {
@@ -528,7 +592,50 @@ function print_pdf_link_allowed($args) {
     $print_pdf_sys_link_visibility = variable_get('print_pdf_sys_link_visibility', PRINT_PDF_SYS_LINK_VISIBILITY_DEFAULT);
     $print_pdf_sys_link_pages = variable_get('print_pdf_sys_link_pages', PRINT_PDF_SYS_LINK_PAGES_DEFAULT);
 
-    return _print_page_match($print_pdf_sys_link_visibility, $print_pdf_sys_link_pages);
+    return _print_page_match($print_pdf_sys_link_visibility, $_GET['q'], $print_pdf_sys_link_pages);
   }
   return FALSE;
 }
+
+/**
+ * Find out the version of the TCPDF library
+ */
+function _print_pdf_tcpdf_version() {
+  $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
+  if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) {
+    // prevent TCPDF default configs
+    define('K_TCPDF_EXTERNAL_CONFIG', TRUE);
+  }
+  require_once($print_pdf_pdf_tool);
+
+  // Hide warnings, as some TCPDF constants may still be undefined
+  @$pdf = new TCPDF();
+
+  if (method_exists($pdf, 'getTCPDFVersion')) {
+    return $pdf->getTCPDFVersion();
+  }
+  else {
+    return 'unknown';
+  }
+}
+
+/**
+ * Find out the version of the wkhtmltopdf library
+ */
+function _print_pdf_wkhtmltopdf_version() {
+  $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT);
+  $descriptor = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
+
+  $cmd = realpath($print_pdf_pdf_tool) .' --version';
+  $process = proc_open($cmd, $descriptor, $pipes, NULL, NULL);
+  if (is_resource($process)) {
+    $content = stream_get_contents($pipes[1]);
+    $out = preg_match('!.*?(\d+\.\d+\.\d+).*$!m', $content, $matches);
+    fclose($pipes[0]);
+    fclose($pipes[1]);
+    fclose($pipes[2]);
+    $retval = proc_terminate($process);
+  }
+
+  return ($matches[1]);
+}