'pdf', 'text' => t('PDF version'), 'description' => t('Display a PDF version of this page.'), 'path' => 'printpdf', 'class' => 'print-pdf', 'icon' => 'pdf_icon.png', 'module' => 'print_pdf', ); } /** * Implements hook_print_new_window_alter(). */ function print_pdf_print_new_window_alter(&$new_window, $format) { $new_window = (variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT) == 1); } /** * Implements hook_permission(). */ function print_pdf_permission() { return array( 'access PDF version' => array( 'title' => t('Access the PDF version'), 'description' => t('View the PDF versions and the links to them in the original pages.'), ), ); } /** * Implements hook_init(). */ function print_pdf_init() { if (variable_get('print_pdf_autoconfig', PRINT_PDF_AUTOCONFIG_DEFAULT)) { $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); $tool = explode('|', $print_pdf_pdf_tool); $function = $tool[0] . '_pdf_tool_info'; $info = function_exists($function) ? $function() : array(); if (isset($info['public_dirs'])) { foreach ($info['public_dirs'] as $dir) { $directory = 'public://print_pdf/' . $tool[0] . '/' . $dir; /** @var DrupalLocalStreamWrapper $wrapper */ $wrapper = file_stream_wrapper_get_instance_by_uri($directory); $real_directory_path = $wrapper->getDirectoryPath() . "/" . file_uri_target($directory); $result = file_prepare_directory($real_directory_path, FILE_CREATE_DIRECTORY); if (!$result) { watchdog('print_pdf', 'Failed to create directory "%dir" for %tool.', array('%dir' => $directory, '%tool' => $tool[0]), WATCHDOG_CRITICAL); } } } } if (variable_get('print_pdf_cache_enabled', PRINT_PDF_CACHE_ENABLED_DEFAULT)) { $directory = print_pdf_cache_dir(); $wrapper = file_stream_wrapper_get_instance_by_uri($directory); $real_directory_path = $wrapper->getDirectoryPath() . "/" . file_uri_target($directory); $result = file_prepare_directory($real_directory_path, FILE_MODIFY_PERMISSIONS | FILE_CREATE_DIRECTORY); if (!$result) { watchdog('print_pdf', 'Failed to create directory "%dir" for print_pdf cache.', array('%dir' => $directory), WATCHDOG_CRITICAL); } } } /** * Implements hook_flush_caches(). */ function print_pdf_flush_caches() { print_pdf_cache_delete(); return array(); } /** * Implements hook_menu(). */ function print_pdf_menu() { $link = print_pdf_print_link(); $items = array(); $items[$link['path']] = array( 'title' => 'Printer-friendly PDF', 'page callback' => 'print_pdf_controller', 'access arguments' => array('access PDF version'), 'type' => MENU_CALLBACK, 'file' => 'print_pdf.pages.inc', ); $items[$link['path'] . '/' . $link['path']] = array( 'access callback' => FALSE, ); $items['admin/config/user-interface/print/pdf'] = array( 'title' => 'PDF', 'description' => 'Configure the settings of the PDF generation functionality.', 'page callback' => 'drupal_get_form', 'page arguments' => array('print_pdf_settings'), 'access arguments' => array('administer print'), 'weight' => 3, 'type' => MENU_LOCAL_TASK, 'file' => 'print_pdf.admin.inc', ); $items['admin/config/user-interface/print/pdf/options'] = array( 'title' => 'Options', 'weight' => -1, 'type' => MENU_DEFAULT_LOCAL_TASK, ); return $items; } /** * Implements hook_variable_info(). */ function print_pdf_variable_info($options) { $link = print_pdf_print_link(); $variable['print_pdf_link_text'] = array( 'title' => t('PDF version'), 'description' => t('Text used in the link to the PDF version.'), 'type' => 'string', 'default' => t($link['text']), ); return $variable; } /** * Implements hook_block_info(). */ function print_pdf_block_info() { $block['print_pdf-top']['info'] = t('Most PDFd'); $block['print_pdf-top']['cache'] = DRUPAL_CACHE_GLOBAL; return $block; } /** * Implements hook_block_view(). */ function print_pdf_block_view($delta = 0) { $block = array(); switch ($delta) { case 'print_pdf-top': $block['subject'] = t('Most PDFd'); $result = db_query_range("SELECT path FROM {print_pdf_page_counter} LEFT JOIN {node} n ON path = CONCAT('node/', n.nid) WHERE status <> 0 OR status IS NULL ORDER BY totalcount DESC", 0, 3) ->fetchAll(); if (count($result)) { $items = array(); foreach ($result as $obj) { $items[] = l(_print_get_title($obj->path), $obj->path); } $block['content'] = theme('item_list', array('items' => $items, 'type' => 'ul')); } break; } return $block; } /** * Implements hook_node_load(). */ function print_pdf_node_load($nodes, $types) { $ids = array(); foreach ($nodes as $node) { $ids[] = $node->nid; } $link = print_pdf_print_link(); $size = 'print_' . $link['format'] . '_size'; $orientation = 'print_' . $link['format'] . '_orientation'; $result = db_query('SELECT nid, size, orientation FROM {print_pdf_node_conf} WHERE nid IN (:nids)', array(':nids' => $ids))->fetchAllAssoc('nid'); foreach ($nodes as $node) { $node->{$size} = (isset($result[$node->nid]) && !empty($result[$node->nid]->size)) ? $result[$node->nid]->size : variable_get($size . '_' . $node->type); $node->{$orientation} = (isset($result[$node->nid]) && !empty($result[$node->nid]->orientation)) ? $result[$node->nid]->orientation : variable_get($orientation . '_' . $node->type); } } /** * Implements hook_node_insert(). */ function print_pdf_node_insert($node) { print_pdf_node_update($node); } /** * Implements hook_node_update(). */ function print_pdf_node_update($node) { if (user_access('administer print') || user_access('node-specific print configuration')) { $link = print_pdf_print_link(); $size = 'print_' . $link['format'] . '_size'; $orientation = 'print_' . $link['format'] . '_orientation'; if (!isset($node->{$size})) { $node->{$size} = variable_get($size . '_' . $node->type); } if (!isset($node->{$orientation})) { $node->{$orientation} = variable_get($orientation . '_' . $node->type); } db_merge('print_pdf_node_conf') ->key(array('nid' => $node->nid)) ->fields(array( 'size' => $node->{$size}, 'orientation' => $node->{$orientation}, )) ->execute(); } print_pdf_cache_delete($node->nid); } /** * Implements hook_node_delete(). */ function print_pdf_node_delete($node) { db_delete('print_pdf_page_counter') ->condition('path', 'node/' . $node->nid) ->execute(); print_pdf_cache_delete($node->nid); } /** * Implements hook_form_alter(). */ function print_pdf_form_alter(&$form, &$form_state, $form_id) { // Add the node-type settings to activate the printer-friendly version link. if ((user_access('administer print') || user_access('node-specific print configuration')) && (($form_id == 'node_type_form') || !empty($form['#node_edit_form']))) { $link = print_pdf_print_link(); $size = 'print_' . $link['format'] . '_size'; $orientation = 'print_' . $link['format'] . '_orientation'; $form['print']['print_' . $link['format']][$size] = array( '#type' => 'select', '#title' => t('Paper size'), '#options' => _print_pdf_paper_sizes(TRUE), '#description' => t('Choose the paper size of the generated PDF.'), ); $form['print']['print_' . $link['format']][$orientation] = array( '#type' => 'select', '#title' => t('Page orientation'), '#options' => array( '' => 'Unchanged', 'portrait' => t('Portrait'), 'landscape' => t('Landscape'), ), '#description' => t('Choose the page orientation of the generated PDF.'), ); if ($form_id == 'node_type_form') { $form['print']['print_' . $link['format']][$size]['#default_value'] = variable_get($size . '_' . $form['#node_type']->type); $form['print']['print_' . $link['format']][$orientation]['#default_value'] = variable_get($orientation . '_' . $form['#node_type']->type); } else { $node = $form['#node']; $form['print']['print_' . $link['format']][$size]['#default_value'] = isset($node->{$size}) ? $node->{$size} : variable_get($size . '_' . $node->type); $form['print']['print_' . $link['format']][$orientation]['#default_value'] = isset($node->{$orientation}) ? $node->{$orientation} : variable_get($orientation . '_' . $node->type); } } } /** * Auxiliary function to display a formatted PDF version link. * * Function made available so that developers may call this function from * their defined pages/blocks. * * @param string $path * Path to be used in the link. If not specified, the current URL is used. * @param object $node * Node object, to be used in checking node access. If the path argument is * not provided, the path used will be node/nid. * @param string $location * Where in the page where the link is being inserted ('link', 'corner', * 'block', 'help'). * * @return bool * string with the HTML link to the printer-friendly page * * @ingroup print_api */ function print_pdf_insert_link($path = NULL, $node = NULL, $location = '') { if (function_exists('print_ui_insert_link')) { return print_ui_insert_link(print_pdf_print_link(), array( 'path' => $path, 'node' => $node, 'location' => $location, )); } else { return FALSE; } } /** * Check if the link to the PDF version is allowed depending on the settings. * * @param array $args * Array containing the possible parameters: * view_mode, node, type, path. * * @return bool * FALSE if not allowed, TRUE otherwise */ function print_pdf_link_allowed($args) { $print_pdf_pdf_tool = variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT); return (user_access('access PDF version') && (!empty($print_pdf_pdf_tool))); } /** * Implements hook_cron(). */ function print_pdf_cron() { print_pdf_cache_clean(); } /** * Removes pdf files for nodes/paths if they are older than the lifetime. */ function print_pdf_cache_clean() { $lifetime = variable_get('print_pdf_cache_lifetime', PRINT_PDF_CACHE_LIFETIME_DEFAULT); if ($lifetime > 0) { $files = file_scan_directory(print_pdf_cache_dir(), '!\d+\.pdf$!'); foreach ($files as $file) { // For all files in the cache directory, see when they were last accessed. $result = db_query("SELECT timestamp FROM {print_pdf_page_counter} WHERE path = :path", array(':path' => 'node/' . $file->name)) ->fetchField(); // Keep the file only if last access was within the cache max life value. if (($result === FALSE) || ($result + $lifetime < REQUEST_TIME)) { print_pdf_cache_delete($file->name); } } } } /** * Returns the cache directory. * * @return string * The scheme://path of the cache directory */ function print_pdf_cache_dir() { global $language_url; $scheme = 'private'; if (!file_stream_wrapper_valid_scheme($scheme)) { $scheme = 'temporary'; } return $scheme . '://print_pdf/cache/' . $language_url->language; } /** * Deletes one or more files from the PDF cache directory. * * @param int $nid * The node ID of the page for which the cached PDF should be deleted. * If not provided, the entire cache directory will be deleted. */ function print_pdf_cache_delete($nid = NULL) { $directory = print_pdf_cache_dir(); if ($nid) { $filename = $directory . '/' . $nid . '.pdf'; if (is_file($filename)) { file_unmanaged_delete($filename); } } else { // If no nid is provided, flush the entire cache. if (is_dir($directory)) { file_unmanaged_delete_recursive($directory); } } } /** * Displays the PDF as inline or a downloadable file. * * @param string $pdf * PDF content string. * @param string $filename * Filename of the generated PDF. * * @return string * The disposed PDF file */ function print_pdf_dispose_content($pdf, $filename) { if (headers_sent()) { exit('Unable to stream pdf: headers already sent'); } header('Cache-Control: private'); header('Content-Type: application/pdf'); $content_disposition = variable_get('print_pdf_content_disposition', PRINT_PDF_CONTENT_DISPOSITION_DEFAULT); $attachment = ($content_disposition == 2) ? 'attachment' : 'inline'; header("Content-Disposition: $attachment; filename=\"$filename\""); echo $pdf; flush(); return TRUE; } /** * Generate a PDF version of the provided HTML. * * @param string $html * HTML content of the PDF. * @param array $meta * Meta information to be used in the PDF * - url: original URL * - name: author's name * - title: Page title * - node: node object. * @param string $filename * (optional) Filename of the generated PDF. * @param string $paper_size * (optional) Paper size of the generated PDF. * @param string $page_orientation * (optional) Page orientation of the generated PDF. * * @return string|null * generated PDF page, or NULL in case of error * * @see print_pdf_controller() * * @ingroup print_api */ function print_pdf_generate_html($html, $meta, $filename = NULL, $paper_size = NULL, $page_orientation = NULL) { $pdf_tool = explode('|', variable_get('print_pdf_pdf_tool', PRINT_PDF_PDF_TOOL_DEFAULT)); module_load_include('inc', $pdf_tool[0], $pdf_tool[0] . '.pages'); $function = $pdf_tool[0] . '_print_pdf_generate'; $pdf = function_exists($function) ? $function($html, $meta, $paper_size, $page_orientation) : NULL; if ($filename) { return print_pdf_dispose_content($pdf, $filename); } return $pdf; } /** * Implements hook_views_api(). */ function print_pdf_views_api() { return array( 'api' => 2.0, 'path' => drupal_get_path('module', 'print_pdf'), ); } /** * Lists all possible paper sizes. * * @param bool $include_default * Flag indicating whether to include the tool's default value. * * @return array * array of strings with the available paper sizes */ function _print_pdf_paper_sizes($include_default = FALSE) { $ret = ($include_default) ? array('' => 'Unchanged') : array(); $ret += array( '4A0' => '4A0', '2A0' => '2A0', 'A0' => 'A0', 'A1' => 'A1', 'A2' => 'A2', 'A3' => 'A3', 'A4' => 'A4', 'A5' => 'A5', 'A6' => 'A6', 'A7' => 'A7', 'A8' => 'A8', 'A9' => 'A9', 'A10' => 'A10', 'B0' => 'B0', 'B1' => 'B1', 'B2' => 'B2', 'B3' => 'B3', 'B4' => 'B4', 'B5' => 'B5', 'B6' => 'B6', 'B7' => 'B7', 'B8' => 'B8', 'B9' => 'B9', 'B10' => 'B10', 'C0' => 'C0', 'C1' => 'C1', 'C2' => 'C2', 'C3' => 'C3', 'C4' => 'C4', 'C5' => 'C5', 'C6' => 'C6', 'C7' => 'C7', 'C8' => 'C8', 'C9' => 'C9', 'C10' => 'C10', 'RA0' => 'RA0', 'RA1' => 'RA1', 'RA2' => 'RA2', 'RA3' => 'RA3', 'RA4' => 'RA4', 'SRA0' => 'SRA0', 'SRA1' => 'SRA1', 'SRA2' => 'SRA2', 'SRA3' => 'SRA3', 'SRA4' => 'SRA4', 'LETTER' => 'Letter', 'LEGAL' => 'Legal', 'EXECUTIVE' => 'Executive', 'FOLIO' => 'Folio', ); return $ret; }