print_pdf.module in Printer, email and PDF versions 7.2
Same filename and directory in other branches
Displays Printer-friendly versions of Drupal pages.
File
print_pdf/print_pdf.moduleView source
<?php
/**
* @file
* Displays Printer-friendly versions of Drupal pages.
*
* @ingroup print
*/
define('PRINT_PDF_PDF_TOOL_DEFAULT', FALSE);
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_FILENAME_DEFAULT', '[site:name] - [node:title] - [node:changed:custom:Y-m-d]');
define('PRINT_PDF_CACHE_ENABLED_DEFAULT', 0);
// 1 day.
define('PRINT_PDF_CACHE_LIFETIME_DEFAULT', 86400);
/**
* Implements hook_print_link().
*/
function print_pdf_print_link() {
return array(
'format' => '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';
try {
$result = db_query('SELECT nid, size, orientation FROM {print_pdf_node_conf} WHERE nid IN (:nids)', array(
':nids' => $ids,
))
->fetchAllAssoc('nid');
} catch (PDOException $ex) {
// An exception may occur when a node is loaded before update 7203 runs.
$result = array();
}
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 no global user object, the user_access call will fail.
if (!isset($GLOBALS['user']) || !is_object($GLOBALS['user'])) {
return;
}
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();
}
//For a book page, not only delete the PDF file for the page but also delete the caching PDF file for the entire book.
if (isset($node->book) && isset($node->book['bid'])) {
//Delete the book PDF file.
print_pdf_cache_delete($node->book['bid']);
}
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;
}
Functions
Constants
Name | Description |
---|---|
PRINT_PDF_AUTOCONFIG_DEFAULT | |
PRINT_PDF_CACHE_ENABLED_DEFAULT | |
PRINT_PDF_CACHE_LIFETIME_DEFAULT | |
PRINT_PDF_CONTENT_DISPOSITION_DEFAULT | |
PRINT_PDF_FILENAME_DEFAULT | |
PRINT_PDF_IMAGES_VIA_FILE_DEFAULT | |
PRINT_PDF_PAGE_ORIENTATION_DEFAULT | |
PRINT_PDF_PAPER_SIZE_DEFAULT | |
PRINT_PDF_PDF_TOOL_DEFAULT | @file Displays Printer-friendly versions of Drupal pages. |