pdfpreview.module in PDFPreview 7.2
Same filename and directory in other branches
This file contains hooks for the pdfpreview module
@author Juanjo Garcia <juanjo.gcia@gmail.com> @author Florian Auer <floeschie@gmail.com>
File
pdfpreview.moduleView source
<?php
/**
* @file
* This file contains hooks for the pdfpreview module
*
* @author Juanjo Garcia <juanjo.gcia@gmail.com>
* @author Florian Auer <floeschie@gmail.com>
*
*/
define('PDFPREVIEW_DEFAULT_QUALITY', 75);
define('PDFPREVIEW_DEFAULT_SIZE', '1024x1024');
define('PDFPREVIEW_DEFAULT_SHOW_DESCRIPTION', 0);
define('PDFPREVIEW_DEFAULT_TAG', 'span');
define('PDFPREVIEW_FILENAMES_MACHINE', 0);
define('PDFPREVIEW_FILENAMES_HUMAN', 1);
define('PDFPREVIEW_DEFAULT_FALLBACK_FORMATTER', 'file_default');
/**
* Implements hook_field_formatter_info()
*
*/
function pdfpreview_field_formatter_info() {
$formatters = array(
'pdfpreview' => array(
'label' => t('PDF Preview'),
'field types' => array(
'file',
),
'description' => 'Displays an snapshot of the first page of the PDF',
'settings' => array(
'image_style' => '',
'image_link' => '',
'show_description' => PDFPREVIEW_DEFAULT_SHOW_DESCRIPTION,
'tag' => PDFPREVIEW_DEFAULT_TAG,
'fallback_formatter' => PDFPREVIEW_DEFAULT_FALLBACK_FORMATTER,
),
),
);
if (module_exists('picture')) {
$formatters['pdfpreview_picture'] = $formatters['pdfpreview'];
$formatters['pdfpreview']['label'] = t('PDF Preview (Image)');
$formatters['pdfpreview_picture']['label'] = t('PDF Preview (Picture)');
}
return $formatters;
}
/**
* Implements hook_field_formatter_info_alter().
*/
function pdfpreview_field_formatter_info_alter(&$info) {
$info['pdfpreview']['settings'] += $info['image']['settings'];
if (isset($info['picture'])) {
$info['pdfpreview_picture']['settings'] += $info['picture']['settings'];
}
}
/**
* Implements hook_field_formatter_settings_form().
*/
function pdfpreview_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$form = array();
// Re-use image or picture formatter setting form.
switch ($instance['display'][$view_mode]['type']) {
case 'pdfpreview':
$form += image_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
break;
case 'pdfpreview_picture':
$instance['display'][$view_mode]['type'] = 'picture';
$form += picture_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
break;
}
// Add additional, PDF Preview only settings.
$settings = $instance['display'][$view_mode]['settings'];
$form['show_description'] = array(
'#type' => 'checkbox',
'#title' => t('Description'),
'#description' => t('Show file description beside image'),
'#options' => array(
0 => t('No'),
1 => t('Yes'),
),
'#default_value' => $settings['show_description'],
);
$form['tag'] = array(
'#type' => 'radios',
'#title' => t('HTML tag'),
'#description' => t('Select which kind of HTML element will be used to theme elements'),
'#options' => array(
'span' => 'span',
'div' => 'div',
),
'#default_value' => $settings['tag'],
);
$form['fallback_formatter'] = array(
'#type' => 'checkbox',
'#title' => t('Fallback to default file formatter'),
'#description' => t('When enabled, non-PDF files will be formatted using a default file formatter.'),
'#default_value' => isset($settings['fallback_formatter']) ? (bool) $settings['fallback_formatter'] : TRUE,
'#return_value' => PDFPREVIEW_DEFAULT_FALLBACK_FORMATTER,
);
return $form;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function pdfpreview_field_formatter_settings_summary($field, $instance, $view_mode) {
// Again, act like the image or picture module.
$summary = '';
switch ($instance['display'][$view_mode]['type']) {
case 'pdfpreview':
$summary .= image_field_formatter_settings_summary($field, $instance, $view_mode);
break;
case 'pdfpreview_picture':
$instance['display'][$view_mode]['type'] = 'picture';
$summary .= picture_field_formatter_settings_summary($field, $instance, $view_mode);
break;
}
$summary .= '<br />' . t('Using %tag as separator', array(
'%tag' => $instance['display'][$view_mode]['settings']['tag'],
));
$summary .= '<br />' . t('Descriptions are %desc', array(
'%desc' => $instance['display'][$view_mode]['settings']['show_description'] ? t('visible') : t('hidden'),
));
if (!isset($instance['display'][$view_mode]['settings']['fallback_formatter']) || $instance['display'][$view_mode]['settings']['fallback_formatter']) {
$summary .= '<br />' . t('Using the default file formatter for non-PDF file.');
}
return $summary;
}
/**
* Implements hook_field_formatter_view()
*
* @see _pdfpreview_create_preview()
*/
function pdfpreview_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'];
$image_items = array();
$non_pdfs = array();
list($preview_width, $preview_height) = explode('x', variable_get('pdfpreview_previewsize', PDFPREVIEW_DEFAULT_SIZE));
foreach ($items as $delta => $item) {
if (isset($item['display']) && !$item['display']) {
continue;
}
//don't show hidden files
if ($item['filemime'] == 'application/pdf' && ($preview_uri = _pdfpreview_create_preview($item))) {
$image_items[$delta] = array(
'fid' => $item['fid'],
'uri' => $preview_uri,
'alt' => isset($item['description']) ? $item['description'] : '',
'width' => $preview_width,
'height' => $preview_height,
'title' => isset($item['description']) ? $item['description'] : '',
'attributes' => array(
'class' => array(
'pdfpreview-file',
),
),
);
}
else {
//For non pdf files, we defer processing.
$non_pdfs[$delta] = $item;
}
}
// Render PDF preview files using the image or picture formatter.
switch ($display['type']) {
case 'pdfpreview':
$element += image_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $image_items, $display);
break;
case 'pdfpreview_picture':
$picture_display = array_merge(array(), $display);
$picture_display['type'] = 'picture';
$element += picture_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $image_items, $picture_display);
break;
}
foreach (element_children($element) as $delta) {
$element[$delta]['#theme_wrappers'][] = 'pdfpreview_formatter';
$element[$delta]['#settings'] = $settings;
$element[$delta]['#fid'] = $items[$delta]['fid'];
}
if ((!isset($settings['fallback_formatter']) || $settings['fallback_formatter']) && !empty($non_pdfs)) {
// Process non PDF files using default file formatter.
module_load_include('inc', 'file', 'file.field');
$display['type'] = 'file_default';
$element = array_merge($element, file_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $non_pdfs, $display));
}
return $element;
}
/**
* Implements hook_menu()
*/
function pdfpreview_menu() {
$items = array(
'admin/config/media/pdfpreview' => array(
'title' => 'PDF Preview',
'description' => 'Configure PDF Preview settings',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'pdfpreview_admin',
),
'type' => MENU_NORMAL_ITEM,
),
);
return $items;
}
/**
* Implements hook_theme().
*
*/
function pdfpreview_theme() {
$theme = array(
'pdfpreview_formatter' => array(
'function' => 'theme_pdfpreview_formatter',
'render element' => 'element',
),
);
return $theme;
}
/**
* Implements hook_file_delete()
*/
function pdfpreview_file_delete($file) {
file_unmanaged_delete(_pdfpreview_output_filename($file));
}
/**
* Implements hook_file_update()
*/
function pdfpreview_file_update($file) {
if ($file->uri != $file->original->uri || $file->filesize != $file->original->filesize) {
file_unmanaged_delete(_pdfpreview_output_filename($file->original));
}
}
// ----- custom module functions ----- //
/**
* Creates the module settings render array
*
* If you want to extend the module's settings form, append the elements you
* need to the $form array. Don't forget to update the pdfpreview_uninstall()
* routine in the pdfpreview.install file as well.
*
*/
function pdfpreview_admin() {
$form = array(
'pdfpreview_pathtoimages' => array(
'#type' => 'textfield',
'#title' => t('Images folder'),
'#description' => t('Path, inside files directory, where snapshots are stored. For example <em>pdfpreview</em>'),
'#default_value' => variable_get('pdfpreview_pathtoimages', 'pdfpreview'),
),
'pdfpreview_previewsize' => array(
'#type' => 'textfield',
'#title' => t('Preview size'),
'#description' => t('Size of the preview in pixels. For example <em>100x100</em>. You must set this to a value big enought to apply your image styles.'),
'#default_value' => variable_get('pdfpreview_previewsize', PDFPREVIEW_DEFAULT_SIZE),
),
'pdfpreview_quality' => array(
'#type' => 'textfield',
'#size' => 3,
'#maxlenght' => 3,
'#title' => t('Image quality'),
'#field_suffix' => '%',
'#description' => t('Image extraction quality in percentage.'),
'#default_value' => variable_get('pdfpreview_quality', PDFPREVIEW_DEFAULT_QUALITY),
),
'pdfpreview_filenames' => array(
'#type' => 'radios',
'#options' => array(
PDFPREVIEW_FILENAMES_MACHINE => t('Filename hash'),
PDFPREVIEW_FILENAMES_HUMAN => t('From pdf filename'),
),
'#default_value' => variable_get('pdfpreview_filenames', PDFPREVIEW_FILENAMES_MACHINE),
'#title' => t('Generated filenames'),
'#description' => t('This changes how filenames will be used on genereated previews. If you change this after some files were generated, you must delete them manually.'),
),
);
// Callback function which checks for existing preview directory on save
$form['#submit'][] = '_pdfpreview_prepare_filesystem';
return system_settings_form($form);
}
/**
* Convert the first page of a PDF document
*
* This function converts the first page of a PDF document using ImageMagick's
* convert executable and returns TRUE on success, FALSE else. You can provide
* optional parameters for the convert executable by simply passing them with
* in an array to the $args parameter. For details about convert arguments see
* the <a href="http://www.imagemagick.org/Usage/basics/#cmdline">ImageMagick
* documentation</a>.
*
* @param $source URI to the PDF file
* @param $dest URI where the preview file will be saved
* @param $args Optional arguments for the convert executable
* @see _imagemagick_convert()
* @see _pdfpreview_create_preview()
*/
function _pdfpreview_convert_first_page($source, $dest, $args = array()) {
$args['background'] = '-background white';
$args['flatten'] = '-flatten';
$args['previewsize'] = '-resize ' . escapeshellarg(variable_get('pdfpreview_previewsize', PDFPREVIEW_DEFAULT_SIZE));
$args['pdfpreview'] = TRUE;
$output_directory = dirname($dest);
if (file_prepare_directory($output_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
return _imagemagick_convert($source, $dest, $args);
}
else {
return FALSE;
}
}
/**
* Implements hook_imagemagick_arguments_alter().
*/
function pdfpreview_imagemagick_arguments_alter(&$args, &$context) {
if (!empty($args['pdfpreview'])) {
$context['source'] .= '[0]';
$args['quality'] = '-quality ' . escapeshellarg(variable_get('pdfpreview_quality', PDFPREVIEW_DEFAULT_QUALITY));
unset($args['pdfpreview']);
}
}
/**
* Creates the PDF preview file and returns its URI.
*
* @param object|array $file
* A Drupal file structure (array or object).
* @return string
* The URI of the newly created preview image, or NULL if the preview image can not be created.
*
* @see _pdfpreview_convert_first_page()
* @see pdfpreview_field_formatter_view()
*/
function _pdfpreview_create_preview($file) {
if (!is_array($file)) {
$file = (array) $file;
}
$output_filename = _pdfpreview_output_filename($file);
// Check if a preview already exists.
if (file_exists($output_filename)) {
// Check if the existing preview is older than the file itself.
if (filemtime($file['uri']) <= filemtime($output_filename)) {
// The existing preview can be used, nothing to do.
return $output_filename;
}
else {
// Delete the existing but out-of-date preview.
file_unmanaged_delete($output_filename);
// Clears cached versions of a the existing preview file in all image styles.
image_path_flush($output_filename);
}
}
if (_pdfpreview_convert_first_page($file['uri'], $output_filename)) {
return $output_filename;
}
else {
return NULL;
}
}
/**
* Generates the filename for the preview
* @paream File $file
* @return Filename for the generated preview
*/
function _pdfpreview_output_filename($file) {
if (!is_object($file)) {
$file = (object) $file;
}
$output_dir = file_default_scheme() . '://' . variable_get('pdfpreview_pathtoimages', 'pdfpreview');
if (variable_get('pdfpreview_filenames', PDFPREVIEW_FILENAMES_MACHINE) == PDFPREVIEW_FILENAMES_HUMAN) {
$filename = basename($file->filename, '.pdf');
if (module_exists('transliteration')) {
$filename = transliteration_clean_filename($filename);
}
return $output_dir . '/' . $file->fid . '-' . $filename . '.jpg';
}
else {
return $output_dir . '/' . md5('pdfpreview' . $file->fid) . '.jpg';
}
}
/**
* Prepare the file system for PDF preview image creation
*
* This function is called after the module's setting form is submitted. It
* checks whether the target directory for preview images exists. If this is not
* the case, the directory will be created.
*
* @see _pdfpreview_admin_settings()
* @see system_settings_form_submit()
*/
function _pdfpreview_prepare_filesystem($form, &$form_state) {
$output_uri = file_default_scheme() . '://' . $form['pdfpreview_pathtoimages']['#value'];
if (!file_prepare_directory($output_uri, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
drupal_set_message(t('Error pepraring directory %dir', array(
'%dir' => $output_uri,
)), 'error');
watchdog('pdfpreview', 'Error creating directory %dir', array(
'%dir' => $output_uri,
), WATCHDOG_ERROR);
}
}
/**
* Default theme function to wrap a rendered PDF preview image.
*
* This function is used to wrap the rendered PDF preview image with a dedicated
* container element. If enabled, the description of the image is also appended.
*
* @param array $variables
* A associative array containing:
* - element: A rendered PDF file preview (using one of the image or picture
* file formatter).
*
* @return string
* A wrapped rendered PDF preview image.
*/
function theme_pdfpreview_formatter($variables) {
$element = $variables['element'];
$item = $element['#item'];
$wrapper_tag = $element['#settings']['tag'];
$description = $element['#settings']['show_description'] && isset($item['description']) ? '<' . $wrapper_tag . ' class="pdfpreview-description">' . $item['description'] . '</' . $wrapper_tag . '>' : '';
return sprintf('<div class="pdfpreview" id="pdfpreview-%s">' . ' <%s class="pdfpreview-image-wrapper">%s</%s>' . ' %s' . '</div>', $item['fid'], $wrapper_tag, $element['#children'], $wrapper_tag, $description);
}
Functions
Constants
Name![]() |
Description |
---|---|
PDFPREVIEW_DEFAULT_FALLBACK_FORMATTER | |
PDFPREVIEW_DEFAULT_QUALITY | @file This file contains hooks for the pdfpreview module |
PDFPREVIEW_DEFAULT_SHOW_DESCRIPTION | |
PDFPREVIEW_DEFAULT_SIZE | |
PDFPREVIEW_DEFAULT_TAG | |
PDFPREVIEW_FILENAMES_HUMAN | |
PDFPREVIEW_FILENAMES_MACHINE |