emthumb.module in Embedded Media Field 6.3
Same filename and directory in other branches
Allows for custom thumbnail overrides to Embedded Media Field.
File
contrib/emthumb/emthumb.moduleView source
<?php
/**
* @file
* Allows for custom thumbnail overrides to Embedded Media Field.
*/
/**
* Implementation of hook_menu().
*/
function emthumb_menu() {
$items['emthumb/js/%/%/%'] = array(
'page callback' => 'emthumb_upload_js',
'page arguments' => array(
2,
3,
4,
),
'access callback' => 'emthumb_edit_access',
'access arguments' => array(
3,
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Access callback for the JavaScript upload and deletion AHAH callbacks.
*
* The content_permissions module provides nice fine-grained permissions for
* us to check, so we can make sure that the user may actually edit the file.
*/
function emthumb_edit_access($field_name) {
if (!content_access('edit', content_fields($field_name))) {
return FALSE;
}
// No content permissions to check, so let's fall back to a more general permission.
return user_access('access content');
}
/**
* Implements hook_emfield_field_extra().
* This is called on field operations to allow us to act on emthumbs.
*/
function emthumb_emfield_field_extra($op, &$node, $field, &$items, $teaser, $page, $module) {
switch ($op) {
case 'load':
// Called after content.module loads default data.
$output = array();
if (count($items)) {
$values = array();
foreach ($items as $delta => $file) {
// For some weird reason this is_array() test is required to
// prevent php from segfaulting apache
$existing_data = array();
if (isset($file['data']) && isset($file['data']['emthumb']) && is_array($file['data']['emthumb'])) {
$existing_data = $file['data']['emthumb'];
$items[$delta]['data']['emthumb'] = $existing_data;
}
// Merge new file with existing data so we include alt tag data.
if (!empty($file['data']['emthumb']['fid'])) {
$thumbnail = _emthumb_file_load($file['data']['emthumb']['fid']);
$items[$delta]['data']['emthumb'] = array_merge($existing_data, $thumbnail);
}
}
return array(
$field['field_name'] => $items,
);
}
break;
case 'rss item':
// Different from load (and others) as it can be, and is, called within
// each $field individually.
$output = array();
if (count($items)) {
$values = array();
foreach ($items as $delta => $file) {
if (empty($file['data']['emthumb']['fid'])) {
continue;
}
$thumbnail = _emthumb_file_load($file['data']['emthumb']['fid']);
if (isset($thumbnail['filepath'])) {
$options = array(
'absolute' => TRUE,
);
$thumbnail['filepath'] = url($thumbnail['filepath'], $options);
$output[$delta]['thumbnail'] = $thumbnail;
}
}
}
return $output;
case 'validate':
//TODO Implement this validate function
break;
case 'insert':
case 'update':
// Called before content.module defaults.
foreach ($items as $delta => $item) {
if (!$items[$delta]['data']['emthumb'] && $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']) {
// This will delete the file if the flag is on
_emthumb_file_update($node, $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['file'], $field, $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['flags']['delete']);
$items[$delta]['data']['emthumb'] = $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['file'];
}
if (empty($items[$delta]['data']['emthumb']) && $field['widget']['emthumb_store_local_thumbnail']) {
// was: variable_get('emthumb_store_local_thumbnail', TRUE)) {
// Fetch remote thumb because we don't have a custom one.
$items[$delta]['data']['emthumb'] = emthumb_fetch_remote_thumbnail($items[$delta], $field);
}
// Add alt text and alt title if necessary.
if (!empty($items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['emthumb_alt'])) {
$items[$delta]['data']['emthumb']['emthumb_alt'] = $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['emthumb_alt'];
}
if (!empty($items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['emthumb_title'])) {
$items[$delta]['data']['emthumb']['emthumb_title'] = $items[$delta]['emthumb']['emthumb']['emthumb']['emthumb']['emthumb_title'];
}
if (isset($items[$delta]['emthumb'])) {
// We're saving in the data property so delete emthumb
unset($items[$delta]['emthumb']);
}
}
// Compact deltas.
$items = array_values($items);
break;
case 'delete':
foreach ($items as $delta => $item) {
_emthumb_file_delete($item['data']['emthumb'], $field['field_name']);
}
break;
}
}
/**
* Process our emthumb element.
*/
function emthumb_widget_element_process($element, $edit, &$form_state) {
$field = $element['#field'];
$field_name = $element['#field_name'];
$type_name = $element['#type_name'];
$delta = $element['#delta'];
$upload_op = 'emthumb_' . $field_name . '_' . $delta . '_upload';
$emthumb_element_name = $field_name . '_' . $delta . '_file';
// First grab the file if it's just been uploaded.
$file = _emthumb_file_upload($form_state, $field_name, $field, $delta, $upload_op, TRUE);
// If there is no uploaded file, check the form cache to see if it was
// uploaded earlier, such as from a preview or AHAH.
// @TODO: Doesn't work with AHAH.
if (empty($file) && isset($form_state['storage']) && isset($form_state['storage']['emthumb']) && isset($form_state['storage']['emthumb'][$upload_op])) {
$file = $form_state['storage']['emthumb'][$upload_op];
}
// If we still don't have a file, then use the version from the node.
if (empty($file) && $form_state['values'] && $form_state['values']['nid'] && ($node = node_load($form_state['values']['nid']))) {
$field_data = $node->{$field_name}[$delta];
if ($node->{$field_name} && !empty($field_data['data']['emthumb'])) {
// Get saved file if we have it.
$file = $field_data['data']['emthumb'];
}
}
// Do not display custom thumb stuff if we don't allow a custom thumb.
if ($field['widget']['emthumb']) {
// Separate from tree becase of that silly things won't be
// displayed if they are a child of '#type' = form issue
$element[$emthumb_element_name] = array(
'#type' => 'file',
'#description' => isset($field['widget']['emthumb_description']) ? $field['widget']['emthumb_description'] : t('If you upload a custom thumbnail, then this will be displayed when the @field thumbnail is called for, overriding any automatic thumbnails by custom providers.', array(
'@field' => $field['widget']['label'],
)),
'#tree' => FALSE,
'#weight' => 9,
);
$element['emthumb-upload'] = array(
'#type' => 'submit',
'#value' => t('Upload'),
'#name' => $upload_op,
'#attributes' => array(
'id' => $field_name . '-attach-button',
),
'#tree' => FALSE,
'#submit' => array(
'node_form_submit_build_node',
'emthumb_widget_upload_button_submit',
),
'#weight' => 10,
);
}
if (isset($file) && isset($file['filepath'])) {
$element['#title'] = t('Replace');
$element['emthumb'] = array(
'#theme' => 'emthumb_edit_image_row',
);
$element['emthumb']['flags']['delete'] = array(
'#type' => 'checkbox',
'#title' => t('Delete'),
'#description' => t("Checking this field causes the thumbnail to be redownloaded, deleting the current thumbnail."),
'#default_value' => 0,
);
$filename = $file['filepath'];
$element['emthumb']['preview'] = array(
'#type' => 'markup',
'#value' => theme('emthumb_image', $file, $file['emthumb_alt'], $file['emthumb_title'], array(
'width' => $field['widget']['thumbnail_width'],
'height' => $field['widget']['thumbnail_height'],
), FALSE),
);
$element['emthumb']['description'] = array(
'#type' => 'markup',
'#value' => '<strong>' . t('Filename:') . ' </strong>' . check_plain($file['filename']),
);
// Overwrite with an input field if custom_alt is flagged.
if ($field['widget']['emthumb_custom_alt']) {
$element['emthumb']['emthumb_alt'] = array(
'#type' => 'textfield',
'#title' => t('Alternate text'),
'#default_value' => $file['emthumb_alt'],
'#description' => t('Alternate text to be displayed if the image cannot be displayed.'),
'#maxlength' => 255,
'#size' => 10,
);
}
// Overwrite with an input field if custom_title is flagged.
if ($field['widget']['emthumb_custom_title']) {
$element['emthumb']['emthumb_title'] = array(
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $file['emthumb_title'],
'#description' => t('Text to be displayed on mouse overs.'),
'#maxlength' => 255,
'#size' => 10,
);
}
$element['emthumb']['file'] = array(
'#type' => 'value',
'#value' => $file,
);
// If this was an uploaded file, we need to save it. Otherwise it will be
// forgotten on node save
$element['emthumb']['replace'] = array(
'#type' => 'markup',
'#value' => $field['widget']['emthumb'] ? t('If a new custom thumbnail is chosen, the current custom thumbnail will be replaced upon submitting the form.') : '',
);
}
else {
if ($field['widget']['emthumb_store_local_thumbnail']) {
$element['emthumb']['no_current_thumb'] = array(
'#type' => 'markup',
'#value' => t('If possible, a remote thumbnail will be downloaded on the next save.'),
);
if ($field['widget']['emthumb'] && emthumb_edit_access($field_name)) {
$element['emthumb']['no_current_thumb']['#value'] .= ' ' . t("Alternatively, you may specify a custom thumbnail in this field.");
}
}
}
if (isset($form_state['clicked_button']) && in_array('node_form_submit', $form_state['clicked_button']['#submit']) && isset($form_state['storage']['emthumb'])) {
// Form is being submitted and we want to empty our storage
// so we can redirect to wherever was specified
if (isset($form_state['storage']['emthumb'][$upload_op])) {
unset($form_state['storage']['emthumb'][$upload_op]);
}
if (empty($form_state['storage']['emthumb'])) {
unset($form_state['storage']['emthumb']);
}
}
return $element;
}
function emthumb_widget_upload_button_submit($form, &$form_state) {
$delta = substr($form_state['clicked_button']['#name'], strrpos($form_state['clicked_button']['#name'], '_', -(strlen('_upload') + 1)) + 1, -strlen('_upload'));
$field_name = substr($form_state['clicked_button']['#name'], strlen('emthumb_'), -strlen("_{$delta}_upload"));
$field = $form['#field_info'][$field_name];
$upload_op = 'emthumb_' . $field_name . '_' . $delta . '_upload';
_emthumb_file_upload($form_state, $field_name, $field, $delta, $upload_op);
}
function _emthumb_file_upload(&$form_state, $field_name, $field, $delta, $upload_op, $from_process = FALSE) {
$limits = array(
'extensions' => 'jpg jpeg gif png',
'file_size' => 0,
'user_size' => 0,
'resolution' => 0,
);
$validators = array(
'file_validate_extensions' => array(
$limits['extensions'],
),
'file_validate_image_resolution' => array(
$limits['resolution'],
),
'file_validate_size' => array(
$limits['file_size'],
$limits['user_size'],
),
);
$filename = $source = $field_name . '_' . $delta . '_file';
if ($file = file_save_upload($filename, $validators, file_create_path($field['widget']['emimport_image_path']), FILE_EXISTS_RENAME)) {
$file = (array) $file;
if (strpos($file['filemime'], 'image') !== FALSE) {
$file = _emthumb_scale_image($file, $field['widget']['emthumb_max_resolution']);
// Store the current file so it's available in a later form_get_cache.
$form_state['storage']['emthumb'][$upload_op] = $file;
}
else {
form_set_error('', t("The file you uploaded was not recognized as an image. Please upload a different image type."));
}
}
else {
if (!$from_process) {
form_set_error('', t("There was an error uploading your file."));
}
}
$file = $file ? $file : array();
return $file;
}
/**
* Scales a newly uploaded image to fit the set resolution.
* @param $file
* The file object representing the image.
* @param $resolution
* The width x height of an image, a string in the form of '[w]/[h]',
* such as '640x480'.
* @return
* The file object with the new filesize and path to scaled image.
*/
function _emthumb_scale_image($file, $resolution = 0) {
$info = image_get_info($file['filepath']);
if ($info) {
list($width, $height) = explode('x', $resolution);
if ($width && $height) {
$result = image_scale($file['filepath'], $file['filepath'], $width, $height);
if ($result) {
$file['filesize'] = filesize($file['filepath']);
drupal_set_message(t('The thumbnail was resized to fit within the maximum allowed resolution of %resolution pixels', array(
'%resolution' => $resolution,
)));
}
}
}
return $file;
}
/**
* Validate callback for emthumb_widget element.
*/
function emthumb_widget_element_validate($element, $form_state) {
return $element;
}
/**
* Implementation of hook_elements().
*/
function emthumb_elements() {
$elements = array();
$elements['emthumb_widget'] = array(
'#input' => TRUE,
'#process' => array(
'emthumb_widget_element_process',
),
'#element_validate' => array(
'emthumb_widget_element_validate',
),
);
return $elements;
}
/**
* Callback from hook_emfield_widget_extra_file_included()
* In Drupal 6, we need to build multipart/form-data forms manually.
* @returns
* TRUE. This ensures the form will handle files properly in d6.
*/
function emthumb_emfield_widget_extra_file_included() {
return TRUE;
}
/**
* Implements hook_emfield_widget_extra().
*
* This is called by _emfield_emfield_widget (in emfield.cck.inc) when
* building the widget on the node form. It creates a file upload element
* so the editor may upload a new thumbnail to replace the provider default.
*/
function emthumb_emfield_widget_extra($form, $form_state, $field, $items, $delta = 0, $module) {
if (module_exists('devel_themer') && (user_access('access devel theme information') || user_access('access devel information'))) {
drupal_set_message(t('Files may not be uploaded while the Theme Developer tool is enabled. It is highly recommended to <a href="!url">disable this module</a> unless it is actively being used.', array(
'!url' => url('admin/build/modules'),
)), 'error');
}
$element = array();
// Construct the thumbnail fieldset with the custom label.
// We do not want this fieldset if there are no items
// and the editor can't upload a thumb
if (!empty($items) && !empty($items[0]['value']) && $field['widget']['emthumb_store_local_thumbnail'] || $field['widget']['emthumb']) {
$field_name = $field['field_name'];
$emthumb_label = isset($field['widget']['emthumb_label']) ? $field['widget']['emthumb_label'] : (isset($field['widget']['label']) ? t('@field custom thumbnail', array(
'@field' => $field['widget']['label'],
)) : t('Custom thumbnail'));
$element['emthumb'] = array(
'#type' => 'fieldset',
'#title' => $emthumb_label,
'#collapsible' => TRUE,
'#collapsed' => $field['widget']['emthumb_start_collapsed'],
'#tree' => TRUE,
// Wrapper for fieldset contents (used by ahah.js).
'#prefix' => '<div id="emthumb-wrapper-' . $field_name . '-' . $delta . '">',
'#suffix' => '</div>',
);
if (isset($field['widget']['emthumb_weight'])) {
$element['emthumb']['#weight'] = $field['widget']['emthumb_weight'];
}
$element['emthumb']['emthumb'] = array(
'#type' => 'emthumb_widget',
'#title' => $field['widget']['emthumb'] ? t('New upload') : '',
'#field' => $field,
'#field_name' => $field['field_name'],
'#type_name' => $field['type_name'],
'#items' => $items,
'#delta' => $delta,
);
}
return $element;
}
/**
* This provides extra widget settings to emfields.
* A checkbox to allow custom thumbnails, max resolution, image path, allow
* custom alt tags, allow custom title tags.
*/
function emthumb_emfield_widget_settings_extra($op, $widget) {
switch ($op) {
case 'form':
$form = array();
$form['emthumb'] = array(
'#type' => 'fieldset',
'#title' => t('Embedded Custom Thumbnails'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['emthumb']['emthumb_store_local_thumbnail'] = array(
'#type' => 'checkbox',
'#title' => t('Store remote thumbnails for this field'),
'#description' => t('If checked, then remote thumbnails will be stored locally for this field..'),
'#default_value' => isset($widget['emthumb_store_local_thumbnail']) ? $widget['emthumb_store_local_thumbnail'] : TRUE,
);
$form['emthumb']['emthumb'] = array(
'#type' => 'checkbox',
'#title' => t('Allow custom thumbnails for this field'),
'#description' => t('If checked, then editors may specify a custom thumbnail to be used, overriding any automatic thumbnails otherwise created.'),
'#default_value' => isset($widget['emthumb']) ? $widget['emthumb'] : FALSE,
);
$form['emthumb']['emthumb_label'] = array(
'#type' => 'textfield',
'#title' => t('Custom thumbnail label'),
'#default_value' => isset($widget['emthumb_label']) ? $widget['emthumb_label'] : t('@field custom thumbnail', array(
'@field' => $widget['label'],
)),
'#description' => t('This label will be displayed when uploading a custom thumbnail.'),
);
$form['emthumb']['emthumb_description'] = array(
'#type' => 'textfield',
'#title' => t('Custom thumbnail description'),
'#default_value' => isset($widget['emthumb_description']) ? $widget['emthumb_description'] : t('If you upload a custom thumbnail, then this will be displayed when the @field thumbnail is called for, overriding any automatic thumbnails by custom providers.', array(
'@field' => $widget['label'],
)),
'#description' => t('This description will be displayed when uploading a custom thumbnail.'),
'#maxlength' => 512,
);
$form['emthumb']['emthumb_max_resolution'] = array(
'#type' => 'textfield',
'#title' => t('Maximum resolution for Images'),
'#default_value' => isset($widget['emthumb_max_resolution']) ? $widget['emthumb_max_resolution'] : 0,
'#size' => 15,
'#maxlength' => 10,
'#description' => t('The maximum allowed custom thumbnail size expressed as WIDTHxHEIGHT (e.g. 640x480). Set to 0 for no restriction.'),
);
$form['emthumb']['emimport_image_path'] = array(
'#type' => 'textfield',
'#title' => t('Image path'),
'#default_value' => isset($widget['emimport_image_path']) ? $widget['emimport_image_path'] : '',
'#description' => t('Optional subdirectory within the "%dir" directory where images will be stored. Do not include trailing slash.', array(
'%dir' => variable_get('file_directory_path', 'files'),
)),
'#after_build' => array(
'emthumb_form_check_directory',
),
);
$form['emthumb']['emthumb_custom_alt'] = array(
'#type' => 'checkbox',
'#title' => t('Enable custom alternate text'),
'#default_value' => isset($widget['emthumb_custom_alt']) ? $widget['emthumb_custom_alt'] : 0,
'#description' => t('Enable custom alternate text for custom thumbnails. Filename will be used if not checked.'),
);
$form['emthumb']['emthumb_custom_title'] = array(
'#type' => 'checkbox',
'#title' => t('Enable custom title text'),
'#default_value' => isset($widget['emthumb_custom_title']) ? $widget['emthumb_custom_title'] : 0,
'#description' => t('Enable custom title text for custom thumbnails. Filename will be used if not checked.'),
);
$form['emthumb']['emthumb_start_collapsed'] = array(
'#type' => 'checkbox',
'#title' => t('Default display is collapsed'),
'#default_value' => isset($widget['emthumb_start_collapsed']) ? $widget['emthumb_start_collapsed'] : 0,
'#description' => t('Enable default display to be collapsed.'),
);
return $form;
case 'save':
return array(
'emthumb',
'emthumb_label',
'emthumb_description',
'emthumb_max_resolution',
'emimport_image_path',
'emthumb_custom_alt',
'emthumb_custom_title',
'emthumb_store_local_thumbnail',
'emthumb_start_collapsed',
);
}
}
/**
* Wrapper function for emthumb_check_directory that accepts a form element
* to validate - if user specified one. Won't allow form submit unless the
* directory exists & is writable
*
* @param $form_element
* The form element containing the name of the directory to check.
*/
function emthumb_form_check_directory($form_element) {
if (!empty($form_element['#value'])) {
emthumb_check_directory($form_element['#value'], $form_element);
}
return $form_element;
}
/**
* Create the image directory relative to the 'files' dir recursively for every
* directory in the path.
*
* @param $directory
* The directory path under files to check, such as 'photo/path/here'
* @param $form_element
* A form element to throw an error on if the directory is not writable
*/
function emthumb_check_directory($directory, $form_element = array()) {
foreach (explode('/', $directory) as $dir) {
$dirs[] = $dir;
$path = file_create_path(implode($dirs, '/'));
file_check_directory($path, FILE_CREATE_DIRECTORY, $form_element['#parents'][0]);
}
return true;
}
/**
* Insert a file into the database.
* @param $node
* Node object file will be associated with.
* @param $file
* File to be inserted, passed by reference since fid should be attached.
* @TODO: use hook_file
*/
function _emthumb_file_insert($node, &$file, $field) {
$field_name = $field['field_name'];
$filepath = file_create_path($field['widget']['emimport_image_path']) . '/' . $file['filename'];
$file = (object) $file;
$status = file_set_status($file, 1);
if (!$status) {
// Include file name in upload error.
drupal_set_message(t('Thumbnail upload (%filename) was unsuccessful.', array(
'%filename' => $file['filename'],
)), 'error');
return FALSE;
}
$file = (array) $file;
}
/**
* update the file record if necessary
* @param $node
* @param $file
* @param $field
*/
function _emthumb_file_update($node, &$file, $field, $delete = FALSE) {
$file = (array) $file;
if ($delete) {
_emthumb_file_delete($file, $field['field_name']);
$file = array();
return array();
}
if (!$file['status']) {
_emthumb_file_insert($node, $file, $field);
return $file;
}
else {
// if fid is not numeric here we should complain.
// else we update the file table.
}
return $file;
}
function _emthumb_file_delete($file, $field_name) {
if (is_numeric($file['fid'])) {
db_query('DELETE FROM {files} WHERE fid = %d', $file['fid']);
}
return file_delete($file['filepath']);
}
function _emthumb_file_load($fid = NULL) {
// Don't bother if we weren't passed an fid.
if (isset($fid)) {
// Test to catch fid, eventual plan to have node_load syntax
// once file_attributes table is complete
if (is_numeric($fid)) {
$result = db_query('SELECT * FROM {files} WHERE fid = %d', $fid);
$file = db_fetch_array($result);
return $file ? $file : array();
}
}
return array();
}
/**
* Return the custom thumbnail URL for an item.
* @param $item
* The field item.
* @return
* The path to the custom thumbnail file.
*/
function emthumb_thumbnail_path($item) {
if (is_array($item['data']['emthumb']) && $item['data']['emthumb']['filepath']) {
return file_create_path($item['data']['emthumb']['filepath']);
}
}
/**
* Menu callback; Shared AHAH callback for uploads and deletions.
*
* This rebuilds the form element for a particular field item. As long as the
* form processing is properly encapsulated in the widget element the form
* should rebuild correctly using FAPI without the need for additional callbacks
* or processing.
*/
function emthumb_upload_js($type_name, $field_name, $delta) {
$field = content_fields($field_name, $type_name);
if (empty($field) || empty($_POST['form_build_id'])) {
// Invalid request.
drupal_set_message(t('An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (@size) that this server supports.', array(
'@size' => format_size(file_upload_max_size()),
)), 'error');
print drupal_to_js(array(
'data' => theme('status_messages'),
));
exit;
}
// Build the new form.
$form_state = array(
'submitted' => FALSE,
);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
if (!$form) {
// Invalid form_build_id.
drupal_set_message(t('An unrecoverable error occurred. This form was missing from the server cache. Try reloading the page and submitting again.'), 'error');
print drupal_to_js(array(
'data' => theme('status_messages'),
));
exit;
}
// Build the form. This calls the file field's #value_callback function and
// saves the uploaded file. Since this form is already marked as cached
// (the #cache property is TRUE), the cache is updated automatically and we
// don't need to call form_set_cache().
$args = $form['#parameters'];
$form_id = array_shift($args);
$form['#post'] = $_POST;
$form = form_builder($form_id, $form, $form_state);
// Update the cached form with the new element at the right place in the form.
if (module_exists('fieldgroup') && ($group_name = _fieldgroup_field_get_group($type_name, $field_name))) {
if (isset($form['#multigroups']) && isset($form['#multigroups'][$group_name][$field_name])) {
$form_element = $form[$group_name][$delta][$field_name]['emthumb'];
}
else {
$form_element = $form[$group_name][$field_name][$delta]['emthumb'];
}
}
else {
$form_element = $form[$field_name][$delta]['emthumb'];
}
if (isset($form_element['_weight'])) {
unset($form_element['_weight']);
}
$output = drupal_render($form_element);
// AHAH is not being nice to us and doesn't know the "other" button (that is,
// either "Upload" or "Delete") yet. Which in turn causes it not to attach
// AHAH behaviours after replacing the element. So we need to tell it first.
// Loop through the JS settings and find the settings needed for our buttons.
$javascript = drupal_add_js(NULL, NULL);
$emthumb_ahah_settings = array();
if (isset($javascript['setting'])) {
foreach ($javascript['setting'] as $settings) {
if (isset($settings['ahah'])) {
foreach ($settings['ahah'] as $id => $ahah_settings) {
if (strpos($id, 'emthumb-upload') || strpos($id, 'emthumb-remove')) {
$emthumb_ahah_settings[$id] = $ahah_settings;
}
}
}
}
}
// Add the AHAH settings needed for our new buttons.
if (!empty($emthumb_ahah_settings)) {
$output .= '<script type="text/javascript">jQuery.extend(Drupal.settings.ahah, ' . drupal_to_js($emthumb_ahah_settings) . ');</script>';
}
$output = theme('status_messages') . $output;
// For some reason, file uploads don't like drupal_json() with its manual
// setting of the text/javascript HTTP header. So use this one instead.
$GLOBALS['devel_shutdown'] = FALSE;
print drupal_to_js(array(
'status' => TRUE,
'data' => $output,
));
exit;
}
/**
* @legacy
*/
function emthumb_thumbnail_url($item) {
if ($item['data']['emthumb']['filepath']) {
return file_create_url($item['data']['emthumb']['filepath']);
}
}
/**
* This fetches the thumbnail from the remote provider for local storage.
*/
function emthumb_fetch_remote_thumbnail($item, $field) {
// Obviously, only go forward if our item has been parsed for a provider.
if ($item['provider']) {
// Get the URL to the original thumbnail.
$thumbnail = emfield_include_invoke($field['module'], $item['provider'], 'thumbnail', $field, $item, 'thumbnail', NULL, $field['widget']['thumbnail_width'], $field['widget']['thumbnail_height'], array());
// Go forward only if we have a URL to go by.
if ($thumbnail) {
// The new file will be associated with the global user.
global $user;
// Attempt to fetch the thumbnail from the provided URL.
$request = drupal_http_request($thumbnail);
// Only go forward if we actually have an image stream.
if ($image = $request->data) {
// Add in our check of the the file name length.
$validators['file_validate_name_length'] = array();
// Allow for transliteration, which will take unicode data and convert
// it to US-ASCII for better file storage.
if (module_exists('transliteration')) {
// Transliterate our original URL.
$thumbnail = transliteration_get($thumbnail);
}
// We need to account for slashes in the value, such as from hulu.
// Thus we'll convert them to dashes.
// Our new filepath will be in the form of emvideo-youtube-xd3ewke.jpg.
$basename = $field['module'] . '-' . $item['provider'] . '-' . str_replace('/', '-', $item['value']) . '.' . pathinfo($thumbnail, PATHINFO_EXTENSION);
// Get the base Drupal files path.
$directory = file_directory_path();
if ($field['widget']['emimport_image_path']) {
// Add the field's image path here.
$directory .= '/' . $field['widget']['emimport_image_path'];
}
// Create a new filepath from our desired filename.
$filepath = file_create_filename($basename, $directory);
// Begin building file object.
$file = new stdClass();
$file->uid = $user->uid;
// Strip out the query if provided.
$basename_arr = parse_url($basename);
$filepath_arr = parse_url($filepath);
$file->filename = $basename_arr['path'];
$file->filepath = $filepath_arr['path'];
// If we have mimedetect, then do so. Otherwise we make a best guess
// based on the filename.
$file->filemime = module_exists('mimedetect') ? mimedetect_mime($file) : file_get_mimetype($file->filename);
// Rename potentially executable files, to help prevent exploits.
if (preg_match('/\\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && substr($file->filename, -4) != '.txt') {
$file->filemime = 'text/plain';
$file->filepath .= '.txt';
$file->filename .= '.txt';
}
// If the destination is not provided, or is not writable, then use the
// temporary directory.
if (empty($dest) || file_check_path($dest) === FALSE) {
$dest = file_directory_temp();
}
$file->source = 'emthumb_fetch_remote_thumbnail';
$file->destination = file_destination($file->filepath, $replace);
$file->filesize = strlen($image);
// Call the validation functions.
$errors = array();
foreach ($validators as $function => $args) {
array_unshift($args, $file);
$errors = array_merge($errors, call_user_func_array($function, $args));
}
// Check for validation errors.
if (!empty($errors)) {
$message = t('The selected file %name could not be saved.', array(
'%name' => $file->filename,
));
if (count($errors) > 1) {
$message .= '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>';
}
else {
$message .= ' ' . array_pop($errors);
}
form_set_error($file->source, $message);
return 0;
}
if (!file_save_data($image, $file->filepath, FILE_EXISTS_RENAME)) {
form_set_error($file->source, t('Thumbnail error. Could not copy provider thumbnail.'));
watchdog('file', 'Upload error. Could not move file %file to destination %destination.', array(
'%file' => $file->filename,
'%destination' => $file->destination,
));
return 0;
}
// If we made it this far it's safe to record this file in the database.
$file->status = FILE_STATUS_PERMANENT;
$file->timestamp = time();
drupal_write_record('files', $file);
// Let modules add additional properties to the yet barebone file object.
// This uses the future hook_file from d7's API. Not sure if anything
// actually uses this right now, but they might in the future.
foreach (module_implements('file_insert') as $module) {
$function = $module . '_file_insert';
$function($file);
}
return (array) $file;
}
}
}
return array();
}
/**
* *********** THEME FUNCTIONS ***********
*/
/**
* Implementation of hook_theme().
*/
function emthumb_theme() {
$themes = array(
'emthumb_view_image' => array(
'arguments' => array(
'file' => NULL,
'alt' => '',
'title' => '',
'attributes' => NULL,
'getsize' => TRUE,
),
),
'emthumb_edit_image_row' => array(
'arguments' => array(
'element' => NULL,
),
),
'emthumb_image' => array(
'arguments' => array(
'file' => NULL,
'alt' => '',
'title' => '',
'attributes' => NULL,
'getsize' => TRUE,
),
),
'emthumb_multiple' => array(
'arguments' => array(
'images' => NULL,
),
),
'emthumb_widget' => array(
'arguments' => array(
'element' => NULL,
),
),
);
if (module_exists('imagecache')) {
foreach (imagecache_presets() as $preset) {
$themes['emthumb_formatter_' . $preset['presetname'] . '_default'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_default',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_linked'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_linked',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_imagelink'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_imagelink',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_path'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_path',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_url'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_url',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_providerlink'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_provider_link',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_full'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_full',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_preview'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_preview',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_colorbox'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_colorbox',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_thickbox'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_thickbox',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_lightbox2'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_lightbox2',
'file' => 'emthumb.theme.inc',
);
$themes['emthumb_formatter_' . $preset['presetname'] . '_shadowbox'] = array(
'arguments' => array(
'element' => NULL,
),
'function' => 'theme_emthumb_imagecache_formatter_shadowbox',
'file' => 'emthumb.theme.inc',
);
}
}
return $themes;
}
/**
* Returns the HTML to display a custom thumbnail image.
*/
function theme_emthumb_image($file, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) {
$file = (array) $file;
$path = file_create_url($file['filepath']);
$alt = empty($alt) ? $file['emthumb_alt'] : $alt;
$title = empty($title) ? $file['emthumb_title'] : $title;
return theme('image', $path, $alt, $title, $attributes, $getsize);
}
/**
* formats an array of images.
* @param images
* array of individually themed images
* @return
* html string
*/
function theme_emthumb_multiple($images) {
return implode("\n", $images);
}
/**
* Returns the image thumbnail.
* @TODO: Is this even being used?
*/
function theme_emthumb_view_image($file, $alt = '', $title = '', $attributes = NULL, $getsize = TRUE) {
return theme('emthumb_image', $file, $alt, $title, $attributes, $getsize);
}
/**
* Theme the emthumb element on the node edit form when there's a custom
* thumbnail already in place.
*/
function theme_emthumb_edit_image_row($element) {
$output = '<div class="emthumb-edit-preview">' . drupal_render($element['preview']) . '</div>';
$output .= '<div class="emthumb-edit-image-detail">';
$output .= '<div class="emthumb-edit-image-flags">' . drupal_render($element['flags']) . '</div>';
$output .= '<div class="emthumb-edit-image-description">' . drupal_render($element['description']);
$output .= '</div>';
$output .= drupal_render($element['emthumb_alt']);
$output .= drupal_render($element['emthumb_title']);
$output .= '</div>';
$output = '<div class="emthumb-edit-image-row clear-block">' . $output . '</div>';
if (isset($element['replace'])) {
$output .= '<div class="emthumb-edit-image-replace">' . drupal_render($element['replace']) . '</div>';
}
return $output;
}
/**
* Theme function for the emthumb_widget element.
*/
function theme_emthumb_widget($element) {
return theme('form_element', $element, $element['#children']);
}
/**
* Implementation of hook_field_formatter_info().
*
* imagecache formatters are named as $presetname_$style
* $style is used to determine how the preset should be rendered.
* If you are implementing custom imagecache formatters please treat _ as
* reserved.
*
* @todo: move the linking functionality up to imagefield and clean up the default image
* integration.
*/
function emthumb_field_formatter_info() {
$formatters = array();
if (!module_exists('imagecache')) {
return $formatters;
}
$field_types = array(
'emvideo',
'emimage',
'emaudio',
);
foreach (imagecache_presets() as $preset) {
$formatters[$preset['presetname'] . '_default'] = array(
'label' => t('@preset image', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_linked'] = array(
'label' => t('@preset image linked to node', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_imagelink'] = array(
'label' => t('@preset image linked to original image', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_path'] = array(
'label' => t('@preset file path', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_url'] = array(
'label' => t('@preset URL', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_providerlink'] = array(
'label' => t('@preset image linked to provider', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_full'] = array(
'label' => t('@preset image -> Full Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
$formatters[$preset['presetname'] . '_preview'] = array(
'label' => t('@preset image -> Preview Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
// Add colorbox formatter if colorbox module exists.
if (module_exists('colorbox')) {
$formatters[$preset['presetname'] . '_colorbox'] = array(
'label' => t('Colorbox: @preset image -> Full Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
}
// Add thickbox formatter if thickbox module exists.
if (module_exists('thickbox')) {
$formatters[$preset['presetname'] . '_thickbox'] = array(
'label' => t('Thickbox: @preset image -> Full Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
}
if (module_exists('lightbox2')) {
$formatters[$preset['presetname'] . '_lightbox2'] = array(
'label' => t('Lightbox2: @preset image -> Full Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
}
if (module_exists('shadowbox')) {
$formatters[$preset['presetname'] . '_shadowbox'] = array(
'label' => t('Shadowbox: @preset image -> Full Size Media', array(
'@preset' => $preset['presetname'],
)),
'field types' => $field_types,
);
}
}
return $formatters;
}
Functions
Name | Description |
---|---|
emthumb_check_directory | Create the image directory relative to the 'files' dir recursively for every directory in the path. |
emthumb_edit_access | Access callback for the JavaScript upload and deletion AHAH callbacks. |
emthumb_elements | Implementation of hook_elements(). |
emthumb_emfield_field_extra | Implements hook_emfield_field_extra(). This is called on field operations to allow us to act on emthumbs. |
emthumb_emfield_widget_extra | Implements hook_emfield_widget_extra(). |
emthumb_emfield_widget_extra_file_included | Callback from hook_emfield_widget_extra_file_included() In Drupal 6, we need to build multipart/form-data forms manually. @returns TRUE. This ensures the form will handle files properly in d6. |
emthumb_emfield_widget_settings_extra | This provides extra widget settings to emfields. A checkbox to allow custom thumbnails, max resolution, image path, allow custom alt tags, allow custom title tags. |
emthumb_fetch_remote_thumbnail | This fetches the thumbnail from the remote provider for local storage. |
emthumb_field_formatter_info | Implementation of hook_field_formatter_info(). |
emthumb_form_check_directory | Wrapper function for emthumb_check_directory that accepts a form element to validate - if user specified one. Won't allow form submit unless the directory exists & is writable |
emthumb_menu | Implementation of hook_menu(). |
emthumb_theme | Implementation of hook_theme(). |
emthumb_thumbnail_path | Return the custom thumbnail URL for an item. |
emthumb_thumbnail_url | @legacy |
emthumb_upload_js | Menu callback; Shared AHAH callback for uploads and deletions. |
emthumb_widget_element_process | Process our emthumb element. |
emthumb_widget_element_validate | Validate callback for emthumb_widget element. |
emthumb_widget_upload_button_submit | |
theme_emthumb_edit_image_row | Theme the emthumb element on the node edit form when there's a custom thumbnail already in place. |
theme_emthumb_image | Returns the HTML to display a custom thumbnail image. |
theme_emthumb_multiple | formats an array of images. |
theme_emthumb_view_image | Returns the image thumbnail. @TODO: Is this even being used? |
theme_emthumb_widget | Theme function for the emthumb_widget element. |
_emthumb_file_delete | |
_emthumb_file_insert | Insert a file into the database. |
_emthumb_file_load | |
_emthumb_file_update | update the file record if necessary |
_emthumb_file_upload | |
_emthumb_scale_image | Scales a newly uploaded image to fit the set resolution. |